Seluruh merge sejauh ini berjalan mulus karena kita sengaja menjaga kedua sisi bekerja pada berkas yang berbeda. Proyek nyata tidak seberuntung itu: dua orang mengubah baris yang sama pada berkas yang sama, dan mesin penggabung tiga arah mendadak tidak punya jawaban. Git tidak menebak, tidak memilih juara — ia menghentikan merge di tengah jalan dan menyerahkan keputusan kepada kita. Kejadian itu bernama merge conflict. Chapter ini mereproduksi konflik sungguhan dari nol, lalu membedah keluarannya baris demi baris: pesan kegagalan, keadaan git status, dan isi berkas yang penuh penanda <<<<<<< sampai >>>>>>>.
Membuat Dua Sisi Bersenggol #
Konflik butuh satu bahan: baris yang sama disunting berbeda di kedua sisi. Repository latihan menyiapkan persis itu pada README.md, sementara satu berkas lain sengaja dibuat aman:
mkdir latihan-konflik && cd latihan-konflik
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Toko Budi\n\nKontak: [email protected]\n' > README.md
git add README.md
git commit -m "Buat README toko"
git switch -c fitur-kontak
printf '# Toko Budi\n\nKontak: [email protected]\n' > README.md
git add README.md
git commit -m "Ganti kontak ke layanan pelanggan"
printf '# Panduan\n1. pilih produk\n' > panduan.md
git add panduan.md
git commit -m "Tambah panduan belanja"
git switch main
printf '# Toko Budi\n\nKontak: [email protected]\n' > README.md
git add README.md
git commit -m "Ganti kontak ke tim penjualan"
git merge fitur-kontakOutput yang Dihasilkan (perintah git merge fitur-kontak):
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.Tiga baris itu menceritakan kegagalan yang rapi. Mari bedah satu per satu:
- Baris 1 (
Auto-merging README.md) — Git tetap mencoba menggabungkanREADME.mdsecara otomatis. “Auto-merging” berarti mesin tiga arah menyisir berkas ini, berhasil pada baris-baris yang tidak bersenggol, lalu menyerah pada satu titik tabrakan. - Baris 2 (
CONFLICT (content): ...) — penanda jenis tabrakan: konflik isi (content) padaREADME.md. KataCONFLICTadalah alarm-nya; teks dalam kurung akan berbeda untuk jenis konflik lain, seperti kita lihat nanti di chapter Menyelesaikan Merge Conflicts . - Baris 3 (
Automatic merge failed; ...) — vonis akhirnya: penggabungan otomatis gagal, perbaiki konfliknya, lalu jalankan commit hasilnya. Perintah ini keluar dengan kode gagal (bukan nol) — shell kita diam-diam mencatatnya.
Keadaan Repository Saat Konflik #
Merge yang gagal meninggalkan repository di keadaan khusus: setengah tergabung. git status membaca kondisi itu dengan jujur:
git statusOutput yang Dihasilkan:
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: panduan.md
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.mdEmpat bagian keluaran ini wajib dibaca berurutan:
On branch main+You have unmerged paths.— kita masih dimain, dan merge belum selesai: ada jalur berkas yang belum punya hasil akhir. Dua petunjuk di bawahnya adalah pintu darurat:git commituntuk menuntaskan, ataugit merge --abortuntuk membatalkan seluruhnya.Changes to be committed:dengannew file: panduan.md— bukti penting yang sering terlewat: berkas yang tidak konflik sudah selesai digabung dan tertinggal di staging area. Panduan belanja dari sisi fitur sudah masuk; hanyaREADME.mdyang macet.Unmerged paths:denganboth modified: README.md— status khas konflik isi: kedua sisi (both) mengubah (modified) berkas yang sama. Di sinilah keputusan menunggu.- Tab tunggal sebelum
new file:danboth modified:adalah format asligit status— bagian tabrakan ditandai lewat status berkas, bukan teks khusus.
Isi Berkas dengan Penanda Konflik #
Tabrakan itu sendiri terpahat langsung di dalam berkas. Git menulis kedua versi yang bersenggol berdampingan, dipisah tiga penanda:
cat README.mdOutput yang Dihasilkan:
# Toko Budi
<<<<<<< HEAD
Kontak: [email protected]
=======
Kontak: [email protected]
>>>>>>> fitur-kontakBlok penanda itu punya anatomi tetap:
<<<<<<< HEAD— pembuka sisi kita: versi pada branch aktif saat merge dijalankan (main), identik dengan alias--oursyang kita pakai nanti.- Baris di bawahnya sampai
=======— isi versi kita:Kontak: [email protected]. =======— garis pembatas kedua sisi, ketujuh tanda sama dengan.- Baris dari
=======sampai>>>>>>>— isi versi seberang:Kontak: [email protected]. >>>>>>> fitur-kontak— penutup sisi seberang: versi dari branch yang digabungkan, alias--theirs.
Baris pertama berkas (# Toko Budi) sama sekali tidak terkena penanda — hanya baris yang benar-benar bersenggol yang dikepung. Penanda ini bukan kode program: ia catatan sementara yang wajib kita hapus saat menyelesaikan konflik.
Mengapa Git Berhenti, Bukan Menebak #
Kembali ke meja tiga arah dari chapter Three-Way Merge
: Git menghadapi tiga versi README.md — versi dasar (titik percabangan, [email protected]), versi main (penjualan@), dan versi fitur-kontak (cs@). Karena ketiganya berbeda pada baris yang sama, tidak ada satu pun sisi yang bisa dinyatakan “tetap tidak berubah” — pola yang biasa dipakai Git untuk memilih pemenang secara aman. Menebak berarti risiko membuang pekerjaan orang; berhenti berarti pekerjaan tidak ada yang hilang.
Pertanyaan itu dijawab lewat empat langkah tenang: baca status, sunting berkas, git add, lalu commit. Alurnya lengkap dengan keluaran nyata ada di chapter berikutnya: Menyelesaikan Merge Conflicts
. Konflik yang dijelaskan Pro Git secara resmi bisa dibaca di git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging
.