Kursus
Dalam situasi tertentu, kita mungkin ingin mengatur ulang keadaan cabang Git lokal agar selaras dengan repositori remote, sehingga membuang perubahan lokal apa pun. Ini biasanya disebut sebagai forced pull.
Hal ini menimbulkan kesalahpahaman bahwa cara untuk mencapai tujuan ini adalah dengan opsi --force pada perintah git pull. Dalam artikel ini, kita pelajari bahwa keduanya adalah hal yang berbeda.
Jika Anda baru menggunakan Git, pertimbangkan untuk membaca terlebih dahulu tutorial Git push dan pull kami.
Kita dapat menimpa keadaan lokal dengan keadaan remote menggunakan perintah berikut, mengganti <branch_name> dengan nama cabang Anda. Tindakan ini akan menghapus seluruh perubahan lokal Anda secara permanen pada cabang tersebut.
git fetch
git reset --hard origin/<branch_name>
Artikel ini akan mengulas secara rinci cara kerja perintah-perintah tersebut. Kita melampaui solusi cepat untuk memahami mekanisme dasarnya, sehingga mempelajari cara yang lebih efektif guna mencapai hasil yang diinginkan tanpa risiko kehilangan perubahan penting. Kita juga meluruskan kesalahpahaman dan mempelajari apa sebenarnya fungsi opsi --force pada git pull.
Kapan Perlu Mempertimbangkan Menimpa Perubahan Lokal
Secara umum, menimpa perubahan lokal dengan cara ini bertentangan dengan penggunaan Git yang dimaksudkan. Hampir untuk setiap situasi, ada alur kerja Git yang tepat untuk menyelesaikannya. Namun, sebagian di antaranya sering kali memerlukan pemahaman Git yang lebih dalam dan memakan waktu lebih lama untuk dijalankan. Meskipun bukan praktik terbaik, menimpa perubahan lokal kadang menjadi cara tercepat untuk menyelesaikan pekerjaan.
Bagi saya, ini biasanya terjadi saat saya mengerjakan sebuah fitur yang belum saya kuasai betul. Saya mulai dengan membuat cabang dan melakukan beberapa commit. Ketika buntu, saya meminta bantuan rekan. Mereka mulai dari commit yang lebih awal, sebelum saya melakukan kesalahan, menyelesaikan masalah, lalu mendorong (push) perubahannya. Pada titik ini, saya perlu mengganti versi lokal saya dengan versi remote yang telah diperbarui sambil membuang perubahan lokal, agar bisa melanjutkan mengerjakan fitur tersebut.
Contoh lain adalah ketika terjadi konflik, dan saya merasa lebih sulit atau lebih memakan waktu untuk memperbaiki konflik daripada menerapkan ulang perubahan kita pada versi kode yang terbaru.
Apa pun alasannya, selalu pastikan bahwa perubahan tersebut memang tidak diperlukan dan aman untuk dihapus atau lakukan pencadangan cabang Anda agar tidak kehilangan pekerjaan penting.
Cara yang Benar untuk Menimpa Perubahan Lokal
Langkah pertama adalah mengambil (mengunduh) konten terbaru dari repositori remote ke mesin lokal kita. Ini dilakukan menggunakan perintah fetch dari git:
git fetch
Secara default, ini akan mengambil konten cabang saat ini yang biasanya kita butuhkan. Kita juga bisa menentukan cabang yang ingin diunduh (mengganti <branch_name> di bawah ini dengan nama cabang yang ingin kita fetch):
git fetch origin/<branch_name>
Atau, kita bisa menggunakan opsi --all untuk mengunduh semuanya:
git fetch –all
Mengambil perubahan dari repositori remote tidak akan memengaruhi file di direktori cabang kerja Anda saat ini. Perintah fetch mengunduh perubahan dari repositori remote tetapi tidak menggabungkannya. Repositori lokal menyimpan pandangan terhadap file lokal dan file remote, dan fetch memperbarui pandangan terhadap file remote.
Setelah mengunduh perubahan dari repositori remote, kita dapat menggunakan perintah reset dari git untuk mengatur ulang cabang kerja saat ini ke keadaan tertentu:
git reset --hard origin/<branch_name>
Opsi --hard diperlukan untuk memastikan bahwa perubahan lokal ditimpa oleh perubahan remote. Pada perintah di atas, kita memilih untuk mengganti cabang kerja saat ini dengan origin/<banch_name> yang merupakan versi remote dari cabang tersebut yang baru saja di-fetch.
Perintah git reset akan menghapus perubahan lokal, meskipun sudah di-commit. Karena itu, disarankan untuk membuat cadangan lokal cabang saat ini sebelum menjalankan perintah tersebut. Ini dapat dilakukan dengan:
git branch <name_of_the_backup_branck>
Ganti <name_of_the_backup_branch> dengan nama yang Anda inginkan untuk cabang cadangan.
Jika digabungkan, kita bisa menimpa semua perubahan lokal dari suatu cabang dengan versi remote terbaru dengan melakukan hal berikut:
git fetch
git branch <name_of_the_backup_branch>
git reset --hard origin/<branch_name>
Jika Anda ingin memperluas pengetahuan tentang bekerja dengan cabang di Git, lihat tutorial Mengkloning Cabang Tertentu di Git.
Pembersihan penuh dengan menghapus file yang tidak dilacak
Git tidak akan menyentuh file yang tidak dilacak (file yang tidak pernah menggunakan git add). Jika kita juga ingin menghapus file-file ini, kita dapat melakukannya dengan:
git clean -fdx
Ini adalah perintah berbahaya yang digunakan untuk menghapus file yang tidak dilacak dari direktori kerja. Sangat penting menggunakan perintah ini dengan hati-hati karena secara permanen menghapus file-file tersebut, sehingga tidak mungkin memulihkannya melalui Git. Berikut rincian opsi perintahnya:
-f: Opsi ini memaksa operasi pembersihan untuk berjalan. Sebagai langkah pengaman untuk mencegah kehilangan data secara tidak sengaja, Git akan menolak menghapus file yang tidak dilacak dari direktori kerja tanpa flag ini.-d: Menginstruksikangit cleanuntuk menghapus tidak hanya file yang tidak dilacak tetapi juga direktori yang tidak dilacak. Secara default,git cleanhanya menargetkan file yang tidak dilacak dan mengabaikan direktori.-x: Secara default,git cleanakan menghormati aturan.gitignoredan tidak menghapus file atau direktori yang cocok dengan pola tersebut. Menyertakan -x menimpa perilaku ini, menginstruksikan Git untuk juga menghapus file/direktori yang diabaikan oleh.gitignoreatau aturan abaikan lainnya. Hasilnya adalah pembersihan yang sangat menyeluruh, menghapus semua file yang tidak dilacak di repositori, termasuk output build, file log, dan artefak terbuat lainnya yang biasanya diabaikan.
Memahami Git Pull
Cara biasa kita memperbarui repositori lokal dengan perubahan dari remote adalah menggunakan perintah git pull. Namun, perintah ini tidak dapat digunakan untuk menimpa perubahan lokal karena git pull akan mencoba menggabungkan versi lokal dengan versi remote.
Di balik layar, git pull melakukan langkah-langkah berikut:
- Menggunakan
git fetchuntuk mengunduh versi terbaru repositori remote. - Menggunakan
git mergeuntuk menggabungkan cabang lokal dan remote.
Karena adanya langkah penggabungan, git pull bukan perintah yang cocok pada situasi ketika kita ingin mengabaikan dan membuang perubahan lokal.

Bagaimana dengan git pull --force?
Dengan melihat dokumentasi perintah git pull kita melihat bahwa ia menyediakan opsi --force. Ada kesalahpahaman umum bahwa opsi ini akan memaksa perintah git pull berjalan dengan menghapus perubahan lokal menggunakan perubahan dari remote.
Ketika kita memberikan opsi --force pada git pull, opsi ini diteruskan ke git fetch. Jadi git pull --force melakukan langkah-langkah berikut:
git fetch --forcegit merge

Kita telah mempelajari bahwa fetch digunakan untuk memperbarui pandangan lokal terhadap repositori remote. Jika satu-satunya perbedaan antara repositori lokal Anda saat ini dan repositori remote adalah beberapa commit yang hilang (cabang lokal tertinggal dari versi remote), maka git fetch akan cukup memperbarui pandangan lokal dengan menambahkan commit baru tersebut ke riwayat.

Namun, bisa saja seseorang menulis ulang riwayat commit cabang remote sehingga tidak kompatibel dengan pandangan lokal. Dalam kasus ini, fetch tidak akan berhasil.

Kita bisa menyiasatinya menggunakan opsi --force yang akan memaksa Git untuk mengabaikan riwayat lokal dan menimpanya dengan riwayat remote.
Kita melihat bahwa opsi --force terkait dengan pemaksaan penimpaan riwayat commit dan tidak ada hubungannya dengan mengabaikan perubahan lokal di direktori cabang kerja.
Mengintegrasikan Perubahan Lokal
Menimpa perubahan lokal dengan perubahan dari remote bukan praktik umum Git, tetapi bisa berguna dalam kasus tertentu ketika kita tidak ingin berurusan dengan konflik atau tidak mementingkan perubahan lokal kita.
Merge
Biasanya, seseorang akan menarik (pull) perubahan dan menangani konflik. Orang cenderung takut menghadapi konflik. Beberapa konflik bisa terasa berat, tetapi itu tidak sering terjadi. Konflik terjadi ketika:
- Baik cabang lokal maupun cabang remote memiliki perubahan pada bagian yang sama dari sebuah file.
- Sebuah file dihapus di satu sisi dan diubah di sisi lain.
Dalam kasus-kasus ini, Git tidak bisa menebak perubahan mana yang ingin kita pertahankan, dan kita perlu memberi tahu secara manual. Git akan menyoroti konflik di file seperti ini:

Untuk menyelesaikan konflik, kita mengedit file dengan menghapus baris-baris ini kecuali yang ingin kita pertahankan. Setelah menangani semua konflik, kita dapat melakukan commit perubahan. Untuk panduan mendalam, lihat tutorial ini tentang cara menyelesaikan konflik merge di Git.
Cherry-pick
Jika kita benar-benar ingin menyamakan dulu versi lokal dengan versi remote lalu pada akhirnya mengintegrasikan perubahan kita, kita bisa membawa commit dari cabang cadangan ke cabang saat ini, seperti ini:
git cherry-pick <commit_hash>
Di sini, <commit_hash> adalah hash dari commit yang ingin kita integrasikan. Ini mengasumsikan bahwa sebelum menjalankan git reset, kita telah membuat cabang cadangan dengan git branch <name_of_the_backup_branck> dan bahwa perubahan lokal telah di-commit.
Untuk menemukan <commit_hash>, kita dapat menampilkan daftar hash commit di cabang cadangan menggunakan perintah berikut:
git log <name_of_the_backup_branck>
Stash
Sebagai alternatif, jika kita tidak ingin melakukan commit perubahan atau membuat cabang cadangan, kita dapat men-stash perubahan sebelum melakukan merge menggunakan:
git stash
Perintah ini dapat digunakan untuk menyimpan sementara pekerjaan saat ini tanpa melakukan commit ke riwayat cabang. Stash menyisihkan modifikasi Anda, memungkinkan Anda memiliki direktori kerja yang bersih.
Setelah reset, kita dapat mengembalikan perubahan menggunakan perintah berikut:
git stash pop
Dengan menggunakan stash, alur kerjanya akan terlihat seperti ini:
git fetch
git stash
git reset --hard origin/<branch_name>
git stash pop
Untuk mempelajari lebih lanjut, lihat cheat sheet dengan perintah stash dan git lainnya.
Kesimpulan
Meskipun bukan praktik terbaik, terkadang kita berada dalam situasi di mana kita hanya ingin membuat cabang lokal sesuai dengan isi cabang remote sambil membuang perubahan lokal kita.
Ada kesalahpahaman bahwa ini dicapai dengan git pull --force. Ini tidak benar karena git pull --force menggabungkan git fetch --force dan git merge. Oleh karena itu, ia berupaya menggabungkan perubahan lokal dengan perubahan remote, bukan menimpanya.
Cara yang benar untuk menimpa perubahan lokal dengan isi repositori remote adalah:
git fetch
git reset --hard origin/<branch_name>
Perintah git reset harus digunakan dengan hati-hati karena akan menghapus perubahan lokal, meskipun sudah di-commit. Jika kita memiliki commit lokal dan telah membuat cabang cadangan, kita dapat mengembalikannya menggunakan git cherry-pick. Jika kita belum melakukan commit dan ingin menyimpan sementara pekerjaan lokal, kita dapat menggunakan git stash sebelum reset lalu git stash pop untuk mengembalikan perubahan.

