Git Pull Force - Cara Menimpa Perubahan Lokal Dengan Git

Saat Anda belajar membuat kode, cepat atau lambat Anda juga akan belajar tentang Sistem Kontrol Versi. Dan meskipun ada banyak alat yang bersaing di bidang ini, salah satunya adalah standar de facto yang digunakan oleh hampir semua orang di industri. Begitu populernya hingga ada perusahaan yang menggunakan namanya dalam branding mereka. Kami berbicara tentang Git, tentunya.

Meskipun Git adalah alat yang ampuh, kekuatannya tersembunyi dengan baik. Ada beberapa konsep penting yang perlu Anda pahami agar benar-benar mahir menggunakan Git. Kabar baiknya adalah begitu Anda mempelajarinya, Anda hampir tidak akan pernah mengalami masalah yang tidak dapat Anda hindari.

Alur Kerja Khas

Dalam alur kerja Git yang khas, Anda akan menggunakan repositori lokal, repositori jarak jauh, dan satu atau beberapa cabang. Repositori menyimpan semua informasi tentang proyek, termasuk seluruh riwayatnya dan semua cabangnya. Cabang pada dasarnya adalah kumpulan perubahan yang mengarah dari proyek kosong ke status saat ini.

Setelah mengkloning repositori, Anda mengerjakan salinan lokal Anda dan memperkenalkan perubahan baru. Sampai Anda mendorong perubahan lokal ke repositori jarak jauh, semua pekerjaan Anda hanya tersedia di mesin Anda.

Saat Anda menyelesaikan tugas, saatnya untuk menyinkronkan dengan repositori jarak jauh. Anda ingin menarik perubahan jarak jauh untuk mengikuti kemajuan proyek, dan Anda ingin mendorong perubahan lokal untuk berbagi pekerjaan Anda dengan orang lain.

Perubahan Lokal

Semuanya baik-baik saja saat Anda dan tim Anda mengerjakan file yang benar-benar terpisah. Apa pun yang terjadi, Anda tidak akan saling menginjak kaki.

Namun, ada kalanya Anda dan rekan satu tim secara bersamaan memperkenalkan perubahan di tempat yang sama. Dan biasanya di situlah masalah dimulai.

Pernahkah Anda mengeksekusi git pullhanya untuk melihat yang ditakuti error: Your local changes to the following files would be overwritten by merge:? Cepat atau lambat, semua orang mengalami masalah itu.

Yang lebih membingungkan di sini adalah Anda tidak ingin menggabungkan apa pun, tarik saja, bukan? Sebenarnya, tarikan sedikit lebih rumit dari yang Anda kira.

Seberapa Tepat Git Pull Bekerja?

Tarik bukanlah operasi tunggal. Ini terdiri dari mengambil data dari server jarak jauh dan kemudian menggabungkan perubahan dengan repositori lokal. Kedua operasi ini dapat dilakukan secara manual jika Anda ingin:

git fetch git merge origin/$CURRENT_BRANCH

Bagian itu origin/$CURRENT_BRANCHberarti:

  • Git akan menggabungkan perubahan dari repositori jarak jauh bernama origin(yang Anda kloning)
  • yang telah ditambahkan ke $CURRENT_BRANCH
  • yang belum ada di cabang check out lokal Anda

Karena Git hanya melakukan penggabungan jika tidak ada perubahan yang tidak mengikat, setiap kali Anda menjalankan git pulldengan perubahan yang tidak mengikat dapat membuat Anda mendapat masalah. Untungnya, ada cara untuk keluar dari masalah dengan utuh!

Kami adalah keluarga

Pendekatan Berbeda

Jika Anda memiliki perubahan lokal tanpa komitmen dan masih ingin menarik versi baru dari server jarak jauh, kasus penggunaan Anda biasanya termasuk dalam salah satu skenario berikut. Antara:

  • Anda tidak peduli dengan perubahan lokal dan ingin menimpanya,
  • Anda sangat peduli dengan perubahan dan ingin menerapkannya setelah perubahan jarak jauh,
  • Anda ingin mengunduh modifikasi jarak jauh tetapi belum menerapkannya

Setiap pendekatan membutuhkan solusi yang berbeda.

Anda Tidak Peduli Dengan Perubahan Lokal

Dalam hal ini, Anda hanya ingin membuang semua perubahan lokal yang tidak terikat. Mungkin Anda memodifikasi file untuk percobaan, tetapi Anda tidak lagi memerlukan modifikasi. Yang Anda pedulikan hanyalah up to date dengan upstream.

Ini berarti Anda menambahkan satu langkah lagi antara mengambil perubahan jarak jauh dan menggabungkannya. Langkah ini akan mengatur ulang cabang ke keadaan tidak dimodifikasi, sehingga memungkinkan git mergeuntuk bekerja.

git fetch git reset --hard HEAD git merge origin/$CURRENT_BRANCH

Jika Anda tidak ingin mengetik nama cabang setiap kali Anda menjalankan perintah ini, Git memiliki cara pintas yang bagus menunjuk ke cabang hulu: @{u}. Cabang upstream adalah cabang dalam repositori jarak jauh tempat Anda mendorong dan mengambil.

Beginilah tampilan perintah di atas dengan pintasan:

git fetch git reset --hard HEAD git merge '@{u}'

Kami mengutip pintasan dalam contoh untuk mencegah shell menafsirkannya.

Anda Sangat Peduli Dengan Perubahan Lokal

Jika perubahan tanpa komitmen Anda penting bagi Anda, ada dua opsi. Anda dapat memasukkannya dan kemudian melakukan git pull, atau Anda dapat menyimpannya.

Menyimpan berarti menyimpan perubahan sejenak untuk dikembalikan lagi nanti. Lebih tepatnya, git stashbuat komit yang tidak terlihat di cabang Anda saat ini, tetapi masih dapat diakses oleh Git.

Untuk mengembalikan perubahan yang disimpan di simpanan terakhir, Anda menggunakan git stash popperintah. Setelah berhasil menerapkan perubahan yang disimpan, perintah ini juga menghapus komit simpanan karena tidak lagi diperlukan.

Alur kerja akan terlihat seperti ini:

git fetch git stash git merge '@{u}' git stash pop

By default, the changes from the stash will become staged. If you want to unstage them, use the command git restore --staged (if using Git newer than 2.25.0).

You Just Want to Download the Remote Changes

The last scenario is a little different from the previous ones. Let's say that you are in the middle of a very messy refactoring. Neither losing the changes nor stashing them is an option. Yet, you still want to have the remote changes available to run git diff against them.

As you have probably figured out, downloading the remote changes does not require git pull at all! git fetch is just enough.

One thing to note is that by default, git fetch will only bring you changes from the current branch. To get all the changes from all the branches, use git fetch --all. And if you'd like to clean up some of the branches that no longer exist in the remote repository, git fetch --all --prune will do the cleaning up!

Some Automation

Have you heard of Git Config? It's a file where Git stores all of the user-configured settings. It resides in your home directory: either as ~/.gitconfig or ~/.config/git/config. You can edit it to add some custom aliases that will be understood as Git commands.

For example, to have a shortcut equivalent to git diff --cached (that shows the difference between the current branch and the staged files), you'd add the following section:

[alias] dc = diff --cached

After that, you can run git dc whenever you wish to review the changes. Going this way, we can set up a few aliases related to the previous use cases.

[alias] pull_force = !"git fetch --all; git reset --hard HEAD; git merge @{u}" pf = pull_force pull_stash = !"git fetch --all; git stash; git merge @{u}; git stash pop"

This way, running git pull_force will overwrite the local changes, while git pull_stash will preserve them.

The Other Git Pull Force

Curious minds may have already discovered that there is such a thing as git pull --force. However, this is a very different beast to what's presented in this article.

It may sound like something that would help us overwrite local changes. Instead, it lets us fetch the changes from one remote branch to a different local branch. git pull --force only modifies the behavior of the fetching part. It is therefore equivalent to git fetch --force.

Like git push, git fetch allows us to specify which local and remote branch do we want to operate on. git fetch origin/feature-1:my-feature will mean that the changes in the feature-1 branch from the remote repository will end up visible on the local branch my-feature. When such an operation modifies the existing history, it is not permitted by Git without an explicit --force parameter.

Just like git push --force allows overwriting remote branches, git fetch --force (or git pull --force) allows overwriting local branches. It is always used with source and destination branches mentioned as parameters. An alternative approach to overwriting local changes using git --pull force could be git pull --force "@{u}:HEAD".

Conclusion

Dunia Git sangat luas. Artikel ini hanya membahas salah satu aspek pemeliharaan repositori: menggabungkan perubahan jarak jauh ke dalam repositori lokal. Bahkan skenario sehari-hari ini mengharuskan kami untuk melihat sedikit lebih mendalam tentang mekanisme internal alat kontrol versi ini.

Mempelajari kasus penggunaan aktual membantu Anda lebih memahami cara kerja Git. Ini, pada gilirannya, akan membuat Anda merasa diberdayakan setiap kali Anda mendapat masalah. Kita semua melakukannya dari waktu ke waktu.