git merge: cara menggabungkan branch dan menyelesaikan konflik
git merge menggabungkan riwayat branch lain ke branch aktif. Jika branch aktif tidak bergerak maju, Git cukup memindahkan penunjuk (fast-forward); jika tidak, dibuat commit merge dengan dua induk. Pindah ke branch tujuan lalu jalankan git merge nama-branch; jika terjadi konflik, perbaiki berkasnya, jalankan git add dan git commit, atau batalkan semuanya dengan git merge --abort.
Apa yang dilakukan git merge
Perintah git merge mengambil perubahan dari branch yang ditentukan dan menyisipkannya ke branch tempat Anda berada sekarang. Arahnya penting: penggabungan dilakukan «ke dalam diri sendiri». Untuk menggabungkan feature/login ke main, Anda harus berpindah ke main lebih dulu, lalu menjalankan penggabungan.
git switch main
git pull # ambil main terbaru dari server
git merge feature/login
Git tidak menyalin baris demi baris secara manual. Ia mencari leluhur bersama dari kedua branch (merge base), membandingkan kedua versi terhadap leluhur itu, lalu menggabungkan perubahannya. Jika kedua sisi mengubah bagian yang berbeda, hasilnya otomatis. Jika mengubah bagian yang sama, terjadi konflik dan Anda yang memutuskan.
Dua mode: fast-forward dan three-way merge
Fast-forward: ketika commit merge tidak diperlukan
Misalkan Anda membuat feature dari main, membuat tiga commit, dan selama itu tidak ada yang menambahkan apa pun ke main. Maka riwayat main hanyalah awal dari riwayat feature. Git cukup memajukan penunjuk main ke commit terakhir feature, tanpa membuat commit baru.
$ git merge feature
Updating 3f2a1c4..9b7e0d2
Fast-forward
src/auth.js | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
Riwayat tetap lurus, tetapi fakta bahwa «di sini pernah ada branch feature» hilang dari riwayat. Kadang ini baik, kadang tidak; lihat bagian tentang --no-ff di bawah.
Three-way merge dan commit merge
Jika kedua branch sama-sama maju dari leluhur bersama, penunjuk tidak bisa sekadar dipindahkan. Git melakukan three-way merge: basis (leluhur), sisi «kita» (branch aktif), dan sisi «mereka» (branch yang digabung). Hasilnya dicatat dalam commit merge tersendiri yang memiliki dua induk.
$ git merge feature
Merge made by the 'ort' strategy.
src/auth.js | 42 ++++++++++++++++++++
src/router.js | 3 +-
2 files changed, 44 insertions(+), 1 deletion(-)
Git akan membuka editor dengan pesan seperti Merge branch 'feature'. Anda bisa membiarkannya atau menambahkan alasan penggabungan. Untuk melihat «percabangan» yang terbentuk, gunakan:
git log --oneline --graph --all
Strategi ort dipakai secara default sejak Git 2.34; sebelumnya strateginya adalah recursive. Untuk pekerjaan sehari-hari, Anda tidak perlu mengubah strategi.
Flag git merge yang berguna
| Flag | Fungsi | Kapan berguna |
|---|---|---|
--no-ff | Selalu membuat commit merge, meskipun fast-forward dimungkinkan | Ingin melihat di riwayat commit mana saja yang berasal dari satu fitur |
--ff-only | Hanya menggabung dengan pemajuan, jika tidak gagal dengan error | Memperbarui branch lokal tanpa commit merge yang tidak disengaja |
--squash | Memasukkan semua perubahan branch ke index, tetapi tidak membuat commit dan tidak mencatat hubungan dengan branch | Ingin mengubah fitur menjadi satu commit yang rapi |
--no-commit | Melakukan penggabungan tetapi berhenti sebelum commit | Ingin memeriksa hasil atau menjalankan tes sebelum dicatat |
-m "teks" | Menentukan pesan commit merge | Penggabungan dalam skrip tanpa editor |
--abort | Membatalkan penggabungan yang sedang berjalan dan mengembalikan keadaan sebelumnya | Konfliknya terlalu banyak dan ingin mulai dari awal |
--continue | Menyelesaikan penggabungan setelah konflik diperbaiki | Alternatif dari git commit pada langkah terakhir |
-X ours / -X theirs | Saat ada potongan yang bertabrakan, otomatis mengambil versi kita atau mereka | Jika Anda yakin versi mana yang benar (hati-hati!) |
--no-ff: menjaga batas sebuah fitur
Banyak tim hanya menggabungkan fitur dengan --no-ff. Dengan begitu, di graf setiap tugas tampak sebagai satu «gelembung» yang bisa dibatalkan sekaligus dengan git revert -m 1 <commit-merge>. Pada fast-forward tidak ada titik seperti itu, sehingga setiap commit harus dibatalkan satu per satu.
--squash: satu commit alih-alih sepuluh
git switch main
git merge --squash feature/login
git commit -m "Login dengan e-mail dan kata sandi"
Setelah --squash, Git tidak menganggap branch itu sudah digabung: git branch -d feature/login akan menolak dengan peringatan «not fully merged». Hapus dengan git branch -D setelah Anda yakin semuanya sudah aman. Jangan lanjutkan pekerjaan di branch yang sama setelah squash: penggabungan berikutnya akan membawa lagi perubahan yang sudah masuk dan hampir pasti menimbulkan konflik.
Konflik penggabungan: cara menyelesaikannya
Konflik adalah situasi kerja yang normal, bukan kecelakaan. Artinya: dua branch mengubah baris yang sama (atau satu menghapus berkas yang diubah oleh yang lain), dan Git tidak mau menebak versi mana yang benar.
$ git merge feature/login
Auto-merging src/config.js
CONFLICT (content): Merge conflict in src/config.js
Automatic merge failed; fix conflicts and then commit the result.
Langkah 1. Lihat apa yang bertabrakan
$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: src/config.js
Langkah 2. Edit berkasnya
Di dalam berkas yang konflik, Git menaruh penanda:
<<<<<<< HEAD
const TIMEOUT = 5000;
=======
const TIMEOUT = 10000;
>>>>>>> feature/login
Bagian atas adalah branch aktif Anda (HEAD), bagian bawah adalah branch yang digabung. Pilih versi yang benar (atau gabungkan keduanya), hapus ketiga baris penanda, lalu simpan berkas. Kesalahan umum adalah lupa menghapus penanda di tengah berkas; sebelum commit, cari penanda yang tersisa: git diff --check akan menandainya.
Langkah 3. Tandai penyelesaian dan selesaikan penggabungan
git add src/config.js
git commit # atau git merge --continue
Jika konflik cukup diselesaikan dengan memilih salah satu sisi, Anda tidak perlu mengedit berkas secara manual:
git checkout --ours src/config.js # ambil versi branch aktif
git checkout --theirs src/config.js # ambil versi branch yang digabung
git add src/config.js
Lebih nyaman di editor
VS Code, IDE dari JetBrains, dan editor lain menampilkan konflik dalam tiga kolom dan menyediakan tombol «terima yang sekarang / yang masuk / keduanya». Anda juga bisa menghubungkan alat eksternal lewat git mergetool. Pengaturan yang berguna: git config --global merge.conflictStyle zdiff3. Dengan ini, penanda juga memuat versi asli dari leluhur bersama, sehingga jelas siapa mengubah apa.
Berubah pikiran: batalkan penggabungan
git merge --abort
Perintah ini mengembalikan folder kerja dan index ke keadaan sebelum git merge. Karena itu, sebelum menggabungkan, pastikan direktori kerja bersih: commit atau simpan dulu pekerjaan yang belum selesai dengan git stash, supaya tidak tercampur dengan hasil penggabungan.
Cara membatalkan merge yang sudah dibuat
Jika commit merge belum dikirim ke server, cara termudah adalah memundurkan branch:
git reset --hard ORIG_HEAD
ORIG_HEAD dicatat Git sebelum operasi berisiko, termasuk penggabungan, dan menunjuk posisi branch sebelum merge. Flag --hard membuang perubahan yang belum di-commit, jadi periksa git status terlebih dahulu.
Jika penggabungan sudah masuk ke repositori bersama, riwayat tidak ditulis ulang. Yang dibuat adalah commit kebalikannya:
git revert -m 1 a1b2c3d
Flag -m 1 menyatakan bahwa induk «utama» adalah induk pertama (branch tempat penggabungan dilakukan). Perhatikan jebakannya: setelah revert seperti ini, Git menganggap commit fitur sudah tergabung. Jika nanti Anda ingin menggabungkan fitur yang sudah diperbaiki, Anda harus membatalkan commit revert itu terlebih dahulu.
Merge dalam kerja tim
git pull adalah fetch ditambah merge
git pull biasa mengunduh perubahan lalu menggabungkan branch remote ke branch lokal. Jika Anda dan rekan sama-sama melakukan commit secara paralel, akan muncul commit «Merge branch 'main' of ...». Untuk menghindari merge teknis seperti itu, atur git config --global pull.ff only (pull gagal jika tidak bisa memajukan, dan Anda yang memutuskan) atau gunakan git pull --rebase.
Pull request dan tombol Merge
Di GitHub dan GitLab, penggabungan biasanya dilakukan lewat pull request atau merge request. Tombol «Create a merge commit» setara dengan git merge --no-ff, «Squash and merge» adalah penggabungan dengan squash, dan «Rebase and merge» adalah penggabungan dengan rebase. Memilih mode mana yang dipakai adalah kesepakatan tim; mekanismenya sama dengan yang ada di konsol.
Memasukkan main ke branch Anda
Branch yang hidup lama akan semakin menjauh dari main, dan konfliknya menumpuk. Secara rutin, tarik branch utama ke branch Anda:
git switch feature/login
git fetch origin
git merge origin/main
Dengan cara ini konflik diselesaikan sedikit demi sedikit saat muncul, dan penggabungan akhir ke main berjalan mulus.
Kesalahan umum
- Menggabungkan ke arah yang salah. Menjalankan
git merge mainsaat berada dimain, atau menggabungkan fitur ke fitur lain. Periksa branch aktif dengangit branch --show-currentsebelum menggabung. - Menggabungkan dengan branch yang usang. Menggabungkan
mainlokal yang sudah seminggu tidak diperbarui. Jalankangit pulldulu, baru merge. - «Your local changes would be overwritten by merge». Ada perubahan belum di-commit di berkas yang sama. Commit atau simpan di stash.
- «refusing to merge unrelated histories». Kedua branch tidak punya leluhur bersama, misalnya repositori lokal dibuat dengan
git initsedangkan remote sudah berisi README. Jika penggabungan memang diperlukan, tambahkan--allow-unrelated-histories. - Penanda konflik ikut ter-commit. Build gagal karena
<<<<<<<. Periksa dengangit diff --checkdan jalankan tes sebelum commit.
Ringkasan
git merge adalah cara aman untuk menyatukan branch: ia tidak menulis ulang commit yang sudah ada, hanya menambah commit baru (atau memajukan penunjuk). Gabungkan ke branch aktif, jaga direktori kerja tetap bersih, gunakan --no-ff jika batas fitur penting, dan --squash jika Anda ingin satu commit. Konflik diselesaikan dalam tiga langkah: edit berkas, git add, lalu git commit; dan git merge --abort selalu mengembalikan Anda ke titik awal. Penggabungan branch dan penyelesaian konflik dilatih dengan praktik dalam kursus Git.
Pertanyaan umum
Apa bedanya git merge dengan git pull?
git pull lebih dulu mengunduh perubahan dari server (git fetch), lalu menggabungkan branch remote ke branch aktif lewat git merge atau, jika diatur, lewat rebase. git merge hanya bekerja dengan apa yang sudah ada secara lokal.
Bisakah beberapa branch digabung sekaligus?
Bisa. git merge fitur-a fitur-b akan melakukan octopus merge dengan beberapa induk, tetapi hanya jika tidak ada konflik. Dalam praktiknya, branch biasanya digabung satu per satu.
Bagaimana cara melihat branch mana yang sudah tergabung ke branch aktif?
git branch --merged menampilkan branch yang sudah sepenuhnya masuk ke branch aktif, sedangkan git branch --no-merged menampilkan yang belum. Branch yang sudah tergabung aman dihapus dengan git branch -d.
Bagaimana cara melihat perubahan apa yang akan dibawa penggabungan sebelum dilakukan?
Jalankan git log main..feature untuk melihat commit yang belum ada di main, dan git diff main...feature untuk melihat perubahan branch relatif terhadap leluhur bersama.
Apa itu ORIG_HEAD setelah merge?
Itu referensi yang disimpan Git sebelum penggabungan, yang menunjuk posisi branch sebelum merge. Dengan git reset --hard ORIG_HEAD, merge lokal yang belum dikirim bisa dibatalkan.
Topik ini dibahas mendalam dengan praktik di kursus “Git dari Nol hingga Pengembang Percaya Diri”.
Ke kursus