Konflik di chapter sebelumnya meninggalkan satu pertanyaan terbuka: versi mana yang benar? Bagian ini menjawabnya dengan empat langkah yang menjadi ritual setiap pengembang Git — baca status, sunting berkas, git add, commit — lalu menutup dengan dua situasi khas: mengambil satu sisi penuh dengan git checkout --ours/--theirs, dan konflik yang lahir dari tabrakan hapus-versus-sunting yang penandanya berbeda. Semua keluaran di bawah hasil eksekusi sungguhan pada Git 2.47.3; alurnya identik di mesin pembaca, dengan hash yang berbeda-beda.
Membangun Ulang Konflik Latihan #
Kita pakai skenario yang sama dengan chapter Merge Conflicts
: kedua branch mengubah baris kontak README.md, dan fitur-kontak menambah panduan.md:
mkdir latihan-selesai && cd latihan-selesai
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.Langkah pertama tetap git status: daftar Unmerged paths dengan status both modified adalah pekerjaan yang menunggu. Pada latihan ini isinya satu berkas saja — README.md.
Sunting Berkas, Pilih atau Gabungkan #
Penyelesaian konflik dimulai di editor, bukan di perintah Git. Tiga pilihan berdiri di meja: ambil versi main (penjualan@), ambil versi fitur-kontak (cs@), atau gabungkan keduanya. Latihan ini memilih jalan ketiga — matriks gabungan — dengan membuang seluruh penanda dan menulis ulang bagian kontak:
printf '# Toko Budi\n\nKontak: [email protected]\nKontak cadangan: [email protected]\n' > README.md
cat README.mdOutput yang Dihasilkan (perintah cat README.md):
# Toko Budi
Kontak: [email protected]
Kontak cadangan: [email protected]Tidak ada lagi <<<<<<<, =======, atau >>>>>>> — keputusan sudah tertulis di dalam berkas. Pola pilih-gabung ini bekerja pada teks apa pun; kuncinya satu: hasil akhir harus berisi yang kita mau, bukan sisa marka mesin.
Tandai Selesai lalu Commit #
Suntingan belum dihitung Git sebagai penyelesaian — statusnya masih unmerged sampai dinyatakan selesai lewat git add:
git add README.md
git statusOutput yang Dihasilkan (perintah git status):
On branch main
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: README.md
new file: panduan.mdBaris All conflicts fixed but you are still merging. menegaskan posisi: semua konflik beres, namun merge belum ditutup — perintah penutupnya tinggal satu. Git bahkan sudah menyiapkan draf pesan commit di berkas internal MERGE_MSG:
cat .git/MERGE_MSGOutput yang Dihasilkan (perintah cat .git/MERGE_MSG):
Merge branch 'fitur-kontak'
# Conflicts:
# README.mdDrafnya berisi Merge branch 'fitur-kontak' berikut catatan berkas yang pernah konflik — itulah pesan yang terlihat di editor ketika git commit dijalankan tanpa -m. Kita pakai pesan yang lebih jelas:
git commit -m "Selesaikan konflik kontak di README"Output yang Dihasilkan:
[main 29a75cc] Selesaikan konflik kontak di READMEgit log --oneline --graph --allOutput yang Dihasilkan:
* 29a75cc Selesaikan konflik kontak di README
|\
| * 5797c4b Tambah panduan belanja
| * e098a09 Ganti kontak ke layanan pelanggan
* | 771cdc6 Ganti kontak ke tim penjualan
|/
* dad4a8f Buat README tokoGrafnya persis bentuk three-way merge: commit penyelesaian 29a75cc berparent dua di puncak main. Commit ini sekaligus jawaban dari git merge --continue — perintah kembar git commit yang lebih disiplin: ia menolak berjalan bila tidak ada merge yang menunggu atau bila masih ada berkas unmerged. Rincian kedua perintah ini di dokumen resmi git-scm.com/docs/git-merge
.
Jalan Pintas: Mengambil Satu Sisi Penuh #
Ketika satu sisi memang layak menang mutlak, suntingan manual bisa dilewati. Repository ketiga menyiapkan dua berkas yang sama-sama konflik — README.md dan pesan.txt:
mkdir latihan-ours && cd latihan-ours
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
printf 'Promo hari ini: gratis ongkir\n' > pesan.txt
git add README.md pesan.txt
git commit -m "Buat README dan pesan promo"
git switch -c fitur-promo
printf '# Toko Budi\n\nKontak: [email protected]\n' > README.md
printf 'Promo hari ini: diskon 20 persen\n' > pesan.txt
git add README.md pesan.txt
git commit -m "Perbarui kontak dan promo"
git switch main
printf '# Toko Budi\n\nKontak: [email protected]\n' > README.md
printf 'Promo hari ini: gratis ongkir di atas Rp100 ribu\n' > pesan.txt
git add README.md pesan.txt
git commit -m "Sesuaikan kontak dan promo"
git merge fitur-promoOutput yang Dihasilkan (perintah git merge fitur-promo):
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Auto-merging pesan.txt
CONFLICT (content): Merge conflict in pesan.txt
Automatic merge failed; fix conflicts and then commit the result.Keputusannya: README.md memihak main, pesan.txt memihak fitur-promo. Satu perintah masing-masing:
git checkout --ours README.md
git checkout --theirs pesan.txtOutput yang Dihasilkan (perintah git checkout --ours README.md):
Updated 1 path from the indexOutput yang Dihasilkan (perintah git checkout --theirs pesan.txt):
Updated 1 path from the indexIsi kedua berkas setelah diambil:
cat README.md
cat pesan.txtOutput yang Dihasilkan (perintah cat README.md):
# Toko Budi
Kontak: [email protected]Output yang Dihasilkan (perintah cat pesan.txt):
Promo hari ini: diskon 20 persenNamanya perlu dihafal karena mudah tertukar: --ours selalu berarti branch aktif saat merge (main), --theirs branch yang dibawa masuk (fitur-promo) — persis makna HEAD dan fitur-promo pada penanda konflik. Satu jebakan: perintah ini tidak menandai penyelesaian:
git status --shortOutput yang Dihasilkan:
UU README.md
UU pesan.txtKode UU pada kedua berkas berarti masih unmerged — git add tetap wajib sebelum commit:
git add README.md pesan.txt
git merge --continueOutput yang Dihasilkan (perintah git merge --continue, editor pesan diterima apa adanya):
[main 293441f] Merge branch 'fitur-promo'git log --oneline --graph --allOutput yang Dihasilkan:
* 293441f Merge branch 'fitur-promo'
|\
| * eb96da2 Perbarui kontak dan promo
* | ff1dd57 Sesuaikan kontak dan promo
|/
* 88e2569 Buat README dan pesan promoKonflik Hapus versus Sunting #
Varian terakhir tidak menyisakan penanda <<<<<<< sama sekali. Skenarionya: satu sisi menghapus berkas, sisi lain menyuntingnya. Repository keempat menyiapkan pesan etalase yang dihapus oleh fitur-bersih tetapi diperbarui oleh main:
mkdir latihan-moddel && cd latihan-moddel
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'Pesan lama: toko tutup setiap Senin\n' > pesan.txt
git add pesan.txt
git commit -m "Tulis pesan etalase"
git switch -c fitur-bersih
git rm pesan.txt
git commit -m "Buang pesan etalase lama"
git switch main
printf 'Pesan lama: toko buka setiap hari\n' > pesan.txt
git add pesan.txt
git commit -m "Perbarui isi pesan etalase"
git merge fitur-bersihOutput yang Dihasilkan (perintah git merge fitur-bersih):
CONFLICT (modify/delete): pesan.txt deleted in fitur-bersih and modified in HEAD. Version HEAD of pesan.txt left in tree.
Automatic merge failed; fix conflicts and then commit the result.Jenisnya terbaca di kurung: modify/delete — dihapus di fitur-bersih, disunting di HEAD. Penanda <<<<<<< tidak muncul karena tidak ada dua teks yang bisa dipajang berdampingan; yang ada satu pertanyaan: berkas ini boleh hidup atau tidak. Statusnya pun berbeda:
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)
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by them: pesan.txt
no changes added to commit (use "git add" and/or "git commit -a")Baris deleted by them: pesan.txt dan petunjuk git add/rm menuntun dua penyelesaian: git add pesan.txt berarti berkas dipertahankan dengan isi versi main, git rm pesan.txt berarti penghapusan diterima. Latihan ini mempertahankannya:
git add pesan.txt
git commit -m "Pertahankan pesan hasil pembaruan"Output yang Dihasilkan (perintah git commit -m "Pertahankan pesan hasil pembaruan"):
[main 92a58ac] Pertahankan pesan hasil pembaruangit log --oneline --graph --allOutput yang Dihasilkan:
* 92a58ac Pertahankan pesan hasil pembaruan
|\
| * 1526a6c Buang pesan etalase lama
* | b2ebb8e Perbarui isi pesan etalase
|/
* 15282a0 Tulis pesan etalaseEmpat langkah itu menuntaskan hampir semua konflik. Untuk tabrakan besar — belasan berkas, ratusan baris — menyunting manual mulai terasa berat, dan di situlah git mergetool masuk: Merge Tools
.