Cara Mengatasi Git Merge Conflict untuk Pemula: Lengkap dengan Contoh Nyata

pindipin
30 August 2026
15 min read
Cara Mengatasi Git Merge Conflict untuk Pemula: Lengkap dengan Contoh Nyata

Kenapa ada file penuh tanda kurung ini?

Kamu baru selesai push kode, lalu jalankan git pull atau git merge. Tiba-tiba terminal menampilkan:

CONFLICT (content): Merge conflict in config.php
Automatic merge failed; fix conflicts and then commit the result.

Kamu buka config.php dan mendapati isinya dipenuhi tanda aneh yang tidak pernah kamu lihat sebelumnya:

<<<<<<< HEAD
'debug' => true,
=======
'debug' => env('APP_DEBUG', false),
>>>>>>> fitur/teman

Perasaan pertama kali melihat ini hampir selalu sama: panik. Apa yang terjadi? Apa kamu sudah merusak repository? Apakah rekan tim akan marah?

Tenang. Konflik bukan error dan bukan kegagalan. Ini adalah cara Git memberitahumu: "Dua perubahan tumpang tindih di sini, aku tidak bisa memilih sendiri mana yang benar — keputusan ada di tanganmu." Terjadi di tim mana pun, di proyek mana pun, dan selalu bisa diselesaikan.

Artikel ini akan membekalimu alur tetap yang berlaku di semua skenario: membaca penanda, memilih versi, menyelesaikan dengan git add dan git commit, mundur dengan --abort saat butuh jalan keluar, plus cara memanfaatkan VS Code, mergetool, dan diff3 untuk konflik yang lebih rumit. Satu janji penting: setiap konflik selalu bisa di-undo. Kamu tidak bisa merusak apa pun secara permanen selama tahu --abort.

Apa Itu Merge Conflict dan Kenapa Terjadi

Merge conflict terjadi saat dua branch mengubah baris yang sama di satu file, atau satu branch mengedit file yang dihapus branch lain. Git tidak bisa memutuskan sendiri versi mana yang "benar", sehingga ia berhenti dan meminta keputusanmu.

Yang perlu dipahami: sebagian besar waktu Git menggabungkan perubahan secara otomatis tanpa masalah. Kalau kamu mengubah baris 10 dan temanmu mengubah baris 50 di file yang sama, Git bisa menggabungkan keduanya — tidak ada tumpang tindih. Konflik hanya muncul di area yang benar-benar tumpang tindih.

Contoh paling klasik: dua developer membuka config.php. Kamu mengubah baris 'debug' dari false menjadi true di branch main. Temanmu mengubah baris yang sama menjadi 'debug' => env('APP_DEBUG', false) di branch fitur/teman. Keduanya mengedit baris yang sama — Git tidak tahu mana yang harus dipertahankan.

Satu hal yang perlu diingat sejak awal: git merge --abort selalu membatalkan merge dan mengembalikan ke kondisi sebelumnya. Jadi tidak perlu takut untuk mencoba menyelesaikan. Satu catatan kecil: kalau ada perubahan yang belum di-commit saat merge dimulai, --abort bisa gagal mengembalikannya dengan sempurna. Pastikan working directory bersih atau sudah commit/stash dulu sebelum merge.

Membaca Conflict Markers: <<<<<<< dan Kawan-kawannya

Saat konflik terjadi, Git menyisipkan conflict markers ke dalam file. Inilah contohnya dari config.php:

<<<<<<< HEAD
'debug' => true,
=======
'debug' => env('APP_DEBUG', false),
>>>>>>> fitur/teman

Cara bacanya:

  • <<<<<<< HEAD — tanda pembuka. Label HEAD menunjukkan versi dari branch yang sedang kamu aktif (ours/kita).
  • Antara <<<<<<< dan ======= — isi versi "ours": perubahan yang sudah ada di branch aktifmu.
  • ======= — pemisah antara dua versi.
  • Antara ======= dan >>>>>>> — isi versi "theirs": perubahan dari branch yang sedang di-merge.
  • >>>>>>> fitur/teman — tanda penutup. Label fitur/teman menunjukkan asal versi lawan.

Label di baris <<<<<<< dan >>>>>>> menunjukkan ref atau commit asal, sehingga kamu langsung tahu versi mana yang berasal dari mana.

Sambil membuka file, jalankan git status untuk melihat daftar file berkonflik:

$ git status
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")

Unmerged paths:
        both modified:   config.php

Status both modified adalah yang paling umum ditemui pemula. Artinya: kedua branch mengedit file yang sama.

Kalau ingin lebih detail, git ls-files -u menampilkan tiga versi index untuk file berkonflik: stage 1 (common ancestor/base), stage 2 (ours/HEAD), dan stage 3 (theirs/MERGE_HEAD). Berguna saat konflik kompleks dan kamu perlu melihat versi asal sebelum perubahan apapun.

Alur Inti: Selesaikan, Stage, Lanjutkan

Setelah memahami penandanya, penyelesaiannya mengikuti pola yang sama di semua skenario:

Langkah 1 — Kenali file berkonflik:

git status

Cari seksi "Unmerged paths" untuk tahu file mana yang perlu dibereskan.

Langkah 2 — Buka file, putuskan isi akhir:

Buka file tersebut di editor. Cari setiap blok <<<<<<< sampai >>>>>>>. Hapus semua penanda, dan pastikan isi yang tersisa adalah yang kamu inginkan — bisa salah satu versi, atau gabungan dari keduanya. Pastikan tidak ada satu pun <<<<<<<, =======, atau >>>>>>> yang tertinggal.

Langkah 3 — Stage file yang sudah resolved:

git add config.php

Perintah ini menandai file sebagai "resolved" di index Git — bukan sekadar menambah ke staging area seperti saat menyiapkan commit biasa. Ini langkah kunci yang sering terlewat. Kalau kamu lupa git add, Git akan menolak melanjutkan dengan pesan: "all conflicts fixed but you are still 'merging'."

Langkah 4 — Lanjutkan operasi:

Perintah lanjutan tergantung skenario:

SkenarioPerintah lanjut
git mergegit commit atau git merge --continue
git pull (default merge)git commit (sama seperti merge)
git pull --rebasegit rebase --continue
git rebasegit rebase --continue
git cherry-pickgit cherry-pick --continue
git revertgit revert --continue

--continue hanya berfungsi setelah semua file berkonflik sudah di-git add. Kalau masih ada satu file yang belum di-stage, perintahnya tidak akan jalan.

Kenapa git commit dan --continue bisa digunakan bergantian di merge? Karena git merge --continue pada dasarnya memanggil git commit di balik layar — perbedaannya --continue memastikan ada operasi merge yang sedang berjalan sebelum melanjutkan.

Kalau kamu merasa salah atau bingung, hentikan segera:

git merge --abort

Semua file kembali seperti sebelum merge dimulai. Tidak ada yang hilang.

Memutuskan: Ours atau Theirs?

Di sinilah kebingungan terbesar pemula muncul. Apa sebenarnya "ours" dan "theirs"?

Saat git merge: orientasi normal

Ketika kamu menjalankan git merge fitur/teman dari branch main:

  • ours = branch yang sedang kamu aktif, yaitu main (HEAD).
  • theirs = branch yang di-merge, yaitu fitur/teman.

Penanda di file akan menampilkan <<<<<<< HEAD untuk versi ours dan >>>>>>> fitur/teman untuk versi theirs. Intuisinya sederhana: "ours = punyaku, theirs = punya orang lain."

Saat git rebase / git pull --rebase: orientasi TERBALIK

Ini poin nomor satu yang sering membingungkan dan menjadi sumber bug karena salah pilih versi.

Saat rebase, orientasi ours/theirs terbalik. Dokumentasi resmi Git menyatakan:

During git rebase and git pull --rebase, ours and theirs may appear swapped; --ours gives the version from the branch the changes are rebased onto, while --theirs gives the version from the branch that holds your work.

Artinya secara praktis:

  • ours = branch tujuan rebase (misalnya main), bukan kode yang sedang kamu kerjakan.
  • theirs = commit pekerjaanmu yang sedang diputar ulang.

Jadi kalau kamu menjalankan git rebase main di branch fitur/login dan ingin tetap memakai kode kerjamu sendiri, kamu harus memilih --theirs, bukan --ours. Kebalikannya dari intuisi awal.

Cara aman: jangan pernah menebak. Selalu baca label di conflict markers atau cek git status sebelum memutuskan.

Perintah cepat memilih satu versi

Kalau kamu sudah yakin ingin mengambil salah satu versi secara utuh (tanpa edit manual), ada perintah singkat:

git checkout --ours config.php
git restore --ours config.php

Kedua perintah melakukan hal sama — git restore --ours adalah padanan modern yang diperkenalkan sejak Git 2.23 (2019), sementara git checkout --ours tetap berfungsi sebagai cara klasik.

Atau untuk versi branch lain:

git checkout --theirs config.php
git restore --theirs config.php

Poin kritis: perintah ini hanya berfungsi untuk file yang sedang berkonflik (unmerged paths). Kamu tidak bisa memakainya di luar kondisi konflik untuk "memilih versi tertentu dari suatu file." Setelah menjalankan perintah ini, tetap harus git add file-nya.

Jangan tertukar dengan -X ours / -X theirs

Ada perintah lain yang namanya serupa tapi beda fungsi:

git merge -X theirs fitur/teman

-X theirs (atau -X ours) adalah opsi strategi yang diberikan saat memulai merge. Ini memerintahkan Git untuk otomatis memihak salah satu sisi di semua area tumpang tindih — tanpa menampilkan konflik sama sekali.

Sedangkan git checkout --ours / git restore --theirs bekerja setelah konflik muncul, memilih satu versi per file dari yang sudah berkonflik. Keduanya berbeda momen dan beda mekanisme — jangan dicampuradukkan.

Menghadapi Konflik di Berbagai Skenario

Semua skenario konflik memakai mesin merge yang sama, sehingga penanda dan cara membacanya identik. Yang berbeda adalah perintah lanjutannya. Semua contoh di bawah memakai file config.php yang sama supaya kamu bisa fokus ke perintah, bukan konteks baru.

git merge <branch>

Ini skenario paling murni. Kamu menjalankan merge, konflik muncul, kamu resolve, lalu commit:

$ git switch main
$ git merge fitur/teman
Auto-merging config.php
CONFLICT (content): Merge conflict in config.php
Automatic merge failed; fix conflicts and then commit the result.

Buka config.php, hapus semua penanda, putuskan isi akhir, lalu:

$ git add config.php
$ git commit

Atau kalau mau membatalkan:

$ git merge --abort

git merge --continue juga bisa dipakai sebagai pengganti git commit — hasilnya sama.

git pull dan git pull --rebase

Secara default, git pull menjalankan fetch lalu merge. Jadi konfliknya sama persis dengan skenario merge di atas — setelah resolve, cukup git add dan git commit.

Yang perlu diperhatikan adalah git pull --rebase. Banyak tim yang mengaktifkan opsi ini (atau mengaturnya lewat git config --global pull.rebase true) supaya riwayat commit lebih bersih. Saat pull --rebase berkonflik, orientasi ours/theirs terbalik seperti yang sudah dijelaskan di bagian sebelumnya.

$ git pull --rebase origin main
Auto-merging config.php
CONFLICT (content): Merge conflict in config.php
error: could not apply abc1234... feat: ubah config
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".

Resolve filenya, lalu:

$ git add config.php
$ git rebase --continue

Kalau rebase melibatkan beberapa commit, konflik bisa muncul lebih dari sekali — setiap kali kamu resolve dan --continue, rebase berpindah ke commit berikutnya. Kalau commit tertentu sudah tidak relevan, bisa dilewat dengan git rebase --skip.

git rebase main

Pola dasarnya sama dengan pull --rebase, tapi kamu yang menginisiasi:

$ git switch fitur/login
$ git rebase main

Konflik bisa muncul di beberapa commit secara berurutan. Resolve satu per satu, git rebase --continue setelah tiap resolusi. Kalau kamu sudah frustrasi dan ingin membatalkan seluruh rebase:

$ git rebase --abort

Semua commit kembali ke posisi semula sebelum rebase dimulai. Perlu diingat: --abort membatalkan seluruh rebase, bukan hanya commit yang sedang berkonflik.

git cherry-pick dan git revert

Skenario ini lebih ringkas karena biasanya hanya melibatkan satu commit.

Cherry-pick:

$ git cherry-pick abc1234
# konflik muncul
$ git add config.php
$ git cherry-pick --continue

Mundur: git cherry-pick --abort. Lewati commit ini: git cherry-pick --skip.

Revert:

$ git revert abc1234
# konflik muncul
$ git add config.php
$ git revert --continue

Mundur: git revert --abort.

git stash pop dan git stash apply

Skenario ini punya jebakan khas yang perlu diketahui. Ketika kamu git stash pop dan working tree sudah berubah sejak stash dibuat, konflik bisa muncul. Penandanya akan berbeda labelnya:

<<<<<<< Updated upstream
'debug' => true,
=======
'debug' => false,
>>>>>>> Stashed changes

Di sini, --theirs mengacu ke isi stash (Stashed changes), sementara --ours adalah versi yang sedang ada di working tree (Updated upstream).

Yang kritis: git stash pop tidak menghapus stash saat konflik terjadi. Normalnya pop = apply + drop (stash langsung terbuang). Tapi kalau apply menghasilkan konflik, drop tidak dilakukan — stash tetap tersimpan di daftar. Ini keamanan dari Git supaya pekerjaan lama tidak hilang begitu saja.

Setelah resolve dan git add, kamu harus menghapus stash secara manual:

$ git stash drop

Atau kalau ingin lebih hati-hati, gunakan git stash apply dulu (yang memang tidak pernah drop otomatis), cek hasilnya, baru git stash drop jika sudah yakin.

Konflik di Pull Request GitHub / Merge Request GitLab

Di GitHub, ketika branch PR kamu berkonflik dengan base branch (misalnya main), tombol "Merge pull request" dinonaktifkan dan muncul pesan: "This branch has conflicts that must be resolved."

Ada dua jalur penyelesaian.

Jalur 1 — Web editor (untuk konflik sederhana):

Klik "Resolve conflicts" di halaman PR. GitHub membuka editor web yang menampilkan file berkonflik dengan conflict markers. Edit langsung di sini, hapus penanda, pilih isi yang benar, lalu klik "Mark as resolved" dan "Commit merge." Tombol merge akan aktif kembali.

Jalur 2 — CLI lokal (untuk konflik rumit atau banyak file):

$ git fetch origin
$ git switch <branch-pr>
$ git merge origin/main
# resolve konflik di semua file
$ git add .
$ git commit
$ git push

Setelah push, tombol "Merge pull request" di GitHub akan aktif kembali.

GitLab punya pola yang sama dengan istilah "Merge request" alih-alih "Pull request." Konflik bisa diselesaikan di lokal lewat CLI, lalu push — atau lewat fitur rebase di GitLab yang bisa menjalankan rebase dari web.

Yang perlu diingat: tidak semua konflik bisa diselesaikan di web. Konflik yang melibatkan banyak file atau perubahan kompleks lebih baik ditangani di lokal di mana kamu punya akses penuh ke editor dan terminal.

Alat Bantu: VS Code, Mergetool, dan diff3

Menyelesaikan konflik secara manual dengan mengedit teks memang selalu bisa dilakukan. Tapi ada alat yang membuat prosesnya lebih cepat dan lebih aman.

VS Code — rekomendasi untuk pemula

VS Code mendeteksi conflict markers secara otomatis dan menampilkan CodeLens tepat di atas setiap blok konflik:

  • Accept Current Change — ambil versi branch aktif (ours).
  • Accept Incoming Change — ambil versi branch yang di-merge (theirs).
  • Accept Both Changes — gabungkan keduanya secara berurutan.
  • Compare Changes — tampilkan diff berdampingan.

Untuk konflik yang lebih rumit, VS Code punya 3-way merge editor yang bisa diakses lewat tombol "Resolve in Merge Editor." Panel ini menampilkan versi Incoming (kiri), Current (kanan), dan Result (bawah). Kamu bisa memilih perubahan lewat checkbox, dan Result ter-update secara real-time. Setelah yakin, klik "Complete Merge."

Merge editor ini aktif secara default di versi modern VS Code dan bekerja untuk konflik dari merge maupun rebase. Satu hal yang tidak boleh dilupakan: setelah selesai di VS Code, kamu tetap harus menjalankan git add dan git commit / --continue di terminal untuk menyelesaikan prosesnya.

git mergetool

git mergetool meluncurkan program GUI eksternal untuk menyelesaikan konflik. Beberapa tool populer: KDiff3, Meld, Beyond Compare, dan vimdiff.

Konfigurasi awal:

git config --global merge.tool meld

Kemudian setelah konflik muncul, jalankan:

git mergetool

Tool yang dipilih akan terbuka dengan empat panel: versi lokal (ours), versi remote (theirs), versi base (common ancestor), dan versi hasil merge. Git men-supply variabel lingkungan $LOCAL, $REMOTE, $BASE, dan $MERGED ke tool yang dijalankan.

Setelah selesai menyimpan di mergetool, tetap jalankan git add dan git commit atau --continue — sama seperti resolusi manual.

diff3 dan zdiff3: melihat versi base

Secara default, conflict markers hanya menampilkan dua versi: ours dan theirs. Ada kalanya kamu perlu melihat versi asal (common ancestor) untuk memahami dari mana masing-masing versi bercabang. Di sinilah diff3 berguna.

git config --global merge.conflictstyle diff3

Setelah diaktifkan, conflict markers akan menambahkan blok dengan penanda ||||||| yang berisi versi base sebelum =======:

<<<<<<< HEAD
'debug' => true,
||||||| merged common ancestor
'debug' => false,
=======
'debug' => env('APP_DEBUG', false),
>>>>>>> fitur/teman

Sekarang kamu bisa melihat bahwa versi asalnya false, kamu mengubah ke true, dan temanmu mengubah ke env('APP_DEBUG', false). Dengan konteks tambahan ini, keputusan jadi lebih mudah.

Ada juga zdiff3 (tersedia sejak Git 2.35) yang mirip diff3 tetapi memangkas baris identik di awal/akhir area konflik sehingga tampilannya lebih ringkas:

git config --global merge.conflictstyle zdiff3

Poin penting: merge.conflictStyle hanya mengubah cara konflik ditampilkan, bukan hasil merge. Git tetap menghitung merge dengan cara yang sama — yang berubah hanyalah tampilan penandanya di dalam file. Jangan khawatir, mengaktifkan diff3 atau zdiff3 tidak akan mengubah apapun dari hasil merge-mu.

Kesalahan Umum dan Solusinya

Berikut beberapa kesalahan yang paling sering menimpa developer pemula saat menghadapi konflik:

KesalahanPenyebabSolusi
Commit berisi <<<<<<<Lupa menghapus conflict markersCari <<<<<<< di file sebelum commit; jalankan build/test
git status menolak lanjutLupa git add setelah mengedit fileJalankan git add <file> dulu
Salah ambil versi saat rebaseOrientasi ours/theirs terbalikPeriksa label di conflict markers; ingat rebase membalik orientasi
git push --force ke branch bersamaPanik, ingin "menghindari" konflikJangan; pakai git pull + resolve, bukan force-push
Stash tetap ada setelah pop + konflikpop tidak auto-drop saat konflikJalankan git stash drop manual setelah resolve
File tiba-tiba hilang atau dikembalikanKonflik delete/modifyPahami deleted by us/thems di git status; git add untuk kembalikan, git rm untuk hapus
Perubahan rekan tiba-tiba hilangPaksa satu sisi (-X ours) tanpa cekHanya pakai -X kalau memang yakin; cek dulu
Kode error setelah resolveIsi resolve secara logik salahJalankan build/test setelah resolve, bukan hanya cek syntax

Praktik Terbaik + Penutup

Beberapa kebiasaan yang akan mengurangi frekuensi dan dampak konflik:

  • Pull rutin dan sering. Branch yang tidak pernah di-pull selama seminggu akan menghasilkan konflik yang lebih besar. Kalau tim menggunakan pull --rebase, aktifkan pull.rebase true di config global.
  • Branch kecil dan pendek. Semakin kecil branch, semakin kecil kemungkinan tumpang tindih. Idealnya satu branch = satu perubahan logis.
  • PR/MR kecil. Review lebih mudah, konflik lebih jarang, dan resolve lebih cepat.
  • Komunikasi tim. Kalau tahu ada file yang sedang dikerjakan orang lain, koordinasi dulu. Hindari touch file yang sama secara bersamaan tanpa alasan.
  • Commit/stash perubahan lokal sebelum merge. Ini memastikan --abort bisa mengembalikan working directory dengan sempurna.
  • Aktifkan diff3 atau zdiff3. Melihat versi base sangat membantu saat konflik kompleks.
  • Pakai VS Code atau mergetool untuk konflik yang melibatkan banyak perubahan — jangan hanya mengandalkan teks editor polos.
  • Berlatih di playground. Buat repo percobaan, sengaja bikin konflik, coba resolve dengan berbagai cara, lalu --abort untuk latihan mundur.

Alur penyelesaian konflik bisa diringkas begini: baca penanda → putuskan isi → git add → lanjutkan. Kalau bingung atau salah pilih, mundur dengan --abort — kamu selalu bisa mulai lagi dari awal.

Untuk mendalami lebih jauh, Pro Git tersedia gratis dengan versi bahasa Indonesia, dokumentasi resmi ada di git-scm.com/docs, dan GitHub Docs tentang merge conflicts memberikan panduan langkah demi langkah yang berguna untuk referensi. Selamat berlatih — konflik tidak lagi harus menakutkan.

Bagikan Artikel:
Diskusi & Komentar

Fitur komentar belum diaktifkan oleh administrator.

Artikel Terkait

Selesai membaca? Kembali ke beranda untuk melihat artikel menarik lainnya.

Kembali ke Beranda