Panduan

git merge: cara menggabungkan branch dan menyelesaikan konflik

Diperbarui: · Skillaria.Top

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

FlagFungsiKapan berguna
--no-ffSelalu membuat commit merge, meskipun fast-forward dimungkinkanIngin melihat di riwayat commit mana saja yang berasal dari satu fitur
--ff-onlyHanya menggabung dengan pemajuan, jika tidak gagal dengan errorMemperbarui branch lokal tanpa commit merge yang tidak disengaja
--squashMemasukkan semua perubahan branch ke index, tetapi tidak membuat commit dan tidak mencatat hubungan dengan branchIngin mengubah fitur menjadi satu commit yang rapi
--no-commitMelakukan penggabungan tetapi berhenti sebelum commitIngin memeriksa hasil atau menjalankan tes sebelum dicatat
-m "teks"Menentukan pesan commit mergePenggabungan dalam skrip tanpa editor
--abortMembatalkan penggabungan yang sedang berjalan dan mengembalikan keadaan sebelumnyaKonfliknya terlalu banyak dan ingin mulai dari awal
--continueMenyelesaikan penggabungan setelah konflik diperbaikiAlternatif dari git commit pada langkah terakhir
-X ours / -X theirsSaat ada potongan yang bertabrakan, otomatis mengambil versi kita atau merekaJika 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 main saat berada di main, atau menggabungkan fitur ke fitur lain. Periksa branch aktif dengan git branch --show-current sebelum menggabung.
  • Menggabungkan dengan branch yang usang. Menggabungkan main lokal yang sudah seminggu tidak diperbarui. Jalankan git pull dulu, 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 init sedangkan remote sudah berisi README. Jika penggabungan memang diperlukan, tambahkan --allow-unrelated-histories.
  • Penanda konflik ikut ter-commit. Build gagal karena <<<<<<<. Periksa dengan git diff --check dan 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.

Pelajari topik ini lewat video

Topik ini dibahas mendalam dengan praktik di kursus “Git dari Nol hingga Pengembang Percaya Diri”.

Ke kursus