Troubleshooting 03 Oct 2026 6 views 0 komentar

Atasi Git Merge Conflict Tanpa Panik - Strategi Resolve Conflict yang Rapi

Atasi Git Merge Conflict Tanpa Panik - Strategi Resolve Conflict yang Rapi

Ada satu momen yang bikin jantung semua developer berdebar: kamu selesai nge-fix bug, udah commit rapi, lalu git pull atau git merge, dan boom - layar terminal penuh dengan <<<<<<< HEAD dan =======. Merge conflict. Ya, yang bikin kepala panas itu.

Saya masih ingat pertama kali ketemu merge conflict. Tim saya dulu empat orang, semua nge-branch dari main di hari yang sama. Pas mau merge semuanya, file config.php konflik di lima tempat. Saya panik, langsung git merge --abort, terus nanya ke senior. Senior itu cuma bilang: "Baca pelan-pelan, hapus yang salah, commit lagi." Ternyata semudah itu - cuma butuh cara berpikir yang tenang dan sistematis.

Dalam artikel ini, saya mau bahas cara atasi git merge conflict dari nol sampai advanced. Kita akan cover conflict di file sederhana, conflict yang kompleks dengan multiple hunks, sampai strategi rebase yang bikin history tetap rapi. Semua dengan contoh nyata yang bisa kamu langsung praktekin.

Apa Itu Merge Conflict dan Kenapa Terjadi?

Merge conflict terjadi ketika dua branch mengubah baris yang sama di file yang sama, dan Git nggak bisa nentukan versi mana yang benar. Git itu smart, tapi bukan telepath. Kalau kamu dan rekan tim sama-sama mengubah baris 10 di index.php, Git nggak akan nebak siapa yang benar - dia kasih kamu kedua versinya dan suruh kamu milih.

Conflict NGGAK terjadi kalau:

  • Perubahan di baris berbeda - Git bisa auto-merge
  • Perubahan di file berbeda - Git merge semua tanpa konflik
  • Satu branch mengubah, branch lain tidak - Git ambil yang berubah

Conflict TERJADI kalau:

  • Dua branch mengubah baris yang sama - Git nggak tahu pilih yang mana
  • Satu branch menghapus file, branch lain mengubahnya - ambiguitas
  • Branch baru dan branch lama same-line changes - kasus paling umum

Struktur Conflict Marker - Cara Baca yang Benar

Saat Git menemukan conflict, dia menandai area konflik dengan tiga marker. Ini formatnya:


<<<<<<< HEAD
$database = "production_db";
=======
$database = "staging_db";
>>>>>>> feature/new-config

Mari kita bedah satu per satu:

  • <<<<<<< HEAD - ini awal konflik. Semua baris di bawah ini adalah versi di branch kamu (branch target / current branch)
  • ======= - pemisah. Baris di atas = versimu, baris di bawah = versi branch lain
  • >>>>>>> feature/new-config - akhir konflik. Menunjukkan branch name yang sedang di-merge

Jadi di contoh di atas, branch kamu pakai production_db, sedangkan branch feature/new-config pakai staging_db. Kamu harus pilih salah satu, atau gabungkan keduanya jadi sesuatu yang baru.

Step 1: Simulasi Conflict - Bikin dan Lihat

Cara terbaik belajar adalah dengan bikin conflict sendiri. Mari kita simulasi:


# Bikin repo baru
mkdir conflict-demo && cd conflict-demo
git init

# Bikin file awal
echo "Line 1" > app.txt
echo "Line 2" >> app.txt
echo "Line 3" >> app.txt
git add app.txt
git commit -m "Initial commit"

# Bikin branch baru dan ubah Line 2
git checkout -b feature/update
sed -i 's/Line 2/Line 2 from feature branch/' app.txt
git commit -am "Update Line 2 in feature"

# Balik ke main dan ubah Line 2 juga
git checkout main
sed -i 's/Line 2/Line 2 from main branch/' app.txt
git commit -am "Update Line 2 in main"

# Sekarang merge - KONFLIK!
git merge feature/update

Outputnya akan kayak gini:


Auto-merging app.txt
CONFLICT (content): Merge conflict in app.txt
Automatic merge failed; fix conflicts and then commit the result.

Sekarang buka app.txt. Kamu akan lihat conflict marker di dalamnya. Inilah momen di mana banyak developer panik. Tenang - ini sebenarnya cuma teks yang perlu kamu rapikan.

Step 2: Resolve Conflict Manual - Cara yang Benar

Buka file yang konflik di editor kamu (VS Code, Neovim, atau apapun). VS Code bahkan punya UI khusus yang nampilin tombol "Accept Current", "Accept Incoming", "Accept Both". Tapi penting untuk paham cara manual dulu sebelum andalkan tool.

Prinsip resolve conflict:

  1. Baca kedua versi dengan teliti - jangan asal pilih
  2. Pahami konteks bisnis - versi mana yang benar untuk production?
  3. Cek apakah bisa digabung - kadang kedua perubahan saling melengkapi
  4. Hapus semua marker - <<<<<<<, =======, >>>>>>> harus dihapus
  5. Test sebelum commit - jangan commit file yang masih rusak

Contoh resolve untuk file config.php:


<<<<<<< HEAD
'debug' => false,
'cache_ttl' => 3600,
=======
'debug' => true,
'cache_ttl' => 3600,
'log_level' => 'debug',
>>>>>>> feature/add-logging

// Setelah resolve (gabungkan yang masuk akal):
'debug' => false, // production: false
'cache_ttl' => 3600, // sama di kedua branch
'log_level' => 'debug', // ambil dari feature branch

Di sini saya ambil debug => false dari main (karena ini untuk production), tapi ambil log_level dari feature branch karena itu fitur baru yang berguna. cache_ttl sama di kedua branch, jadi tinggal pakai.

Setelah resolve, lanjut:


# Tandai file sebagai sudah di-resolve
git add config.php

# Lanjutkan merge
git commit -m "Merge feature/add-logging: keep production debug=false, add log_level"

# Kalau mau batal, jangan commit - abort saja
# git merge --abort

Step 3: VS Code dan Tool Visual - Resolve yang Cepat

VS Code adalah editor favorit banyak developer karena conflict resolvernya intuitif banget. Saat kamu buka file yang konflik, VS Code nampilin:

  • Highlight hijau untuk versi current (HEAD)
  • Highlight biru untuk versi incoming (branch yang di-merge)
  • Tombol di atas setiap conflict: Accept Current Change, Accept Incoming Change, Accept Both Changes, Compare Changes

Klik tombol yang sesuai, dan VS Code otomatis hapus conflict marker. Ini super cepat untuk conflict sederhana, tapi tetap perlu review manual untuk yang kompleks.

Tool alternatif lain yang powerful:


# Git mergetool - launch tool visual seperti meld, kdiff3, atau vimdiff
git mergetool

# Setting default merge tool
git config --global merge.tool vimdiff
git config --global mergetool.prompt false

# Kalau pakai meld (Linux/GNOME)
sudo apt install meld
git config --global merge.tool meld

Tool visual kayak meld menampilkan tiga panel side-by-side: local (kiri), base (tengah), remote (kanan). Kamu bisa lihat perbedaan visual dan tarik-tebak baris yang mau dipakai. Untuk conflict yang melibatkan banyak file, ini jauh lebih cepat dari edit manual.

Step 4: Conflict yang Kompleks - Multiple Hunks

Kadang satu file punya konflik di banyak tempat (disebut multiple hunks). Contoh:


<<<<<<< HEAD
function getUser($id) {
 return $this->db->query("SELECT * FROM users WHERE id = ?", [$id]);
}
=======
function getUser($id) {
 $user = $this->db->query("SELECT * FROM users WHERE id = ?", [$id]);
 $this->cache->set("user_{$id}", $user, 300);
 return $user;
}
>>>>>>> feature/caching

// ... baris lain yang nggak konflik ...

<<<<<<< HEAD
function deleteUser($id) {
 return $this->db->query("DELETE FROM users WHERE id = ?", [$id]);
}
=======
function deleteUser($id) {
 $this->db->query("DELETE FROM users WHERE id = ?", [$id]);
 $this->cache->delete("user_{$id}");
 return true;
}
>>>>>>> feature/caching

Di sini ada dua conflict hunks dalam satu file. Strategi resolve:

  1. Resolve satu per satu - jangan try to fix semuanya sekaligus
  2. Pahami pola - di contoh ini, feature/caching menambahkan cache logic ke setiap method. Kalau itu fitur yang mau dipakai, resolve dengan ambil versi feature branch
  3. Konsisten - kalau kamu ambil cache logic di hunk pertama, ambil juga di hunk kedua
  4. Test setelah resolve - jalankan aplikasi, pastikan caching bekerja

Step 5: Abort, Reset, dan Strategy Kalau Bingung

Kadang kamu mulai resolve, tapi di tengah jalan sadar kalau kamu salah pilih atau terlalu rumit. Jangan maksain. Git kasih kamu exit ramp:


# Batal merge sepenuhnya - kembali ke state sebelum merge
git merge --abort

# Kalau kamu sudah git add tapi belum commit
git reset --hard HEAD

# Kalau kamu sudah commit tapi mau batal
git reset --hard HEAD~1

# Lihat status merge
git status

# Lihat file mana saja yang konflik
git diff --name-only --diff-filter=U

Tip penting: Kalau kamu konflik di lebih dari 10 file, kemungkinan branch kamu udah terlalu jauh diverging. Pertimbangkan untuk abort, pull rebase dari main, dan resolve conflict lebih dini:


# Abort dulu
git merge --abort

# Rebase branch kamu ke main, resolve conflict satu per satu
git rebase main

# Setiap conflict di-resolve
git add .
git rebase --continue

# Kalau mau skip commit tertentu
git rebase --skip

# Kalau mau batal rebase
git rebase --abort

Strategi Mencegah Conflict - Lebih Baik Cegah daripada Obat

Resolve conflict itu skill, tapi mencegah conflict itu seni. Berikut praktik yang bisa kamu terapkan di tim:

  • Branch pendek dan sering merge - semakin lama branch hidup, semakin banyak konflik. Target: merge dalam 1-3 hari
  • Bagi file berdasarkan ownership - kalau satu orang kerja di auth.php dan lainnya di payment.php, konflik minim
  • Pull/rebase dari main sebelum mulai kerja - git pull --rebase origin main di awal hari
  • Komunikasi tim - kalau akan ubah file core, bilang di grup dulu
  • Gunakan .gitattributes untuk strategi merge - bisa set merge strategy per file type

Contoh .gitattributes yang membantu:


# Lock file: always take theirs (auto-resolve)
package-lock.json merge=ours
yarn.lock merge=ours

# Binary files: never text merge
*.png binary
*.jpg binary
*.pdf binary

# PHP files: use diff3 style for better context
*.php diff=3

Aktifkan diff3 style biar conflict marker menampilkan versi base juga (lebih mudah paham konteks):


git config --global merge.conflictStyle diff3

Dengan diff3, conflict marker jadi:


<<<<<<< HEAD
$debug = false;
||||||| merged common ancestor
$debug = true;
=======
$debug = false;
$log_level = 'debug';
>>>>>>> feature/logging

Bagian ||||||| menunjukkan versi asli sebelum kedua branch mengubah. Ini super berguna untuk paham apa yang sebenarnya berubah - bukan cuma lihat dua versi tanpa konteks.

Conflict di Binary Files dan File Besar

Binary files (gambar, PDF, video) nggak bisa di-resolve secara teks. Git akan kasih warning dan kamu harus pilih salah satu:


# Pilih versi current branch
git checkout --ours assets/logo.png

# Pilih versi incoming branch
git checkout --theirs assets/logo.png

# Tandai resolved
git add assets/logo.png

Untuk file besar kayak .lock atau generated files, strategi terbaik adalah selalu ambil satu sisi (lihat .gitattributes di atas) atau jangan simpan file generated di Git sama sekali - pakai .gitignore.

Conflict di Git Rebase - Beda dengan Merge

Rebase itu replaying commit satu per satu di atas branch target. Artinya, kalau ada konflik, kamu resolve PER COMMIT, bukan semua sekaligus seperti merge. Ini bisa lebih tedious tapi hasilnya history yang lebih rapi.


# Rebase feature branch ke main
git checkout feature/my-feature
git rebase main

# Kalau conflict:
# 1. Resolve di editor
# 2. git add file
# 3. git rebase --continue
# 4. Ulangi untuk setiap commit yang konflik

# Kalau mau skip commit tertentu
git rebase --skip

# Kalau kapok dan mau batal
git rebase --abort

Pro tip: Sebelum rebase, pastikan working directory bersih. git stash kalau ada perubahan yang belum di-commit:


git stash
git rebase main
git stash pop

Cherry-Pick Conflict - Kasus Khusus

Kadang kamu mau ambil satu commit dari branch lain tanpa merge seluruh branch. git cherry-pick bisa juga menyebabkan conflict:


# Ambil commit tertentu dari branch lain
git cherry-pick abc1234

# Kalau conflict, resolve seperti biasa
# Lalu:
git add .
git cherry-pick --continue

# Batal:
git cherry-pick --abort

Cherry-pick conflict lebih simple karena cuma satu commit. Tapi hati-hati: cherry-pick bisa bikin history duplikat kalau tidak dikelola dengan baik.

Automasi: git rerere (Reuse Recorded Resolution)

Git punya fitur tersembunyi yang super powerful: rerere (reuse recorded resolution). Kalau kamu resolve conflict yang sama berulang kali (misal di rebase berulang), Git akan ingat resolusi yang kamu pilih dan auto-apply.


# Aktifkan sekali untuk semua repo
git config --global rerere.enabled true

# Sekarang setiap kali kamu resolve conflict,
# Git akan record dan reuse di konflik yang sama

Ini berguna banget kalau kamu sering rebase branch yang sama ke main yang terus berubah. Daripada resolve conflict yang sama lima kali, rerere akan auto-resolve setelah kamu resolve sekali.

Cek Hasil Merge Sebelum Commit

Setelah resolve semua conflict, sebelum commit, pastikan tidak ada marker tersisa:


# Cari conflict marker yang tersisa
grep -rn "<<<<<<< HEAD" .
grep -rn "=======" .
grep -rn ">>>>>>>" .

# Kalau ada hasil, berarti masih ada conflict belum di-resolve
# Atau pakai git untuk cek
git diff --check

git diff --check akan nampilin conflict marker dan whitespace error. Run ini selalu sebelum commit merge.

Kesimpulan

Merge conflict itu bukan musuh - itu Git yang jujur bilang "saya nggak tahu mana yang benar, tolong kamu yang tentukan." Dengan pemahaman tentang conflict marker, strategi resolve yang sistematis, dan tool yang tepat (VS Code, meld, rerere), kamu bisa handle conflict tanpa panik.

Inti yang perlu diingat: baca kedua versi, pahami konteks bisnis, resolve dengan tenang, dan test sebelum commit. Dan kalau bingung, git merge --abort selalu jadi exit ramp yang aman.

Oh ya, satu tips terakhir: aktifkan diff3 conflict style dan rerere. Dua config kecil ini akan hemat waktu kamu berjam-jam dalam jangka panjang. Trust me.

Pernah ketemu conflict yang super ribing? Atau punya strategi resolve favorit sendiri? Share di kolom komentar, saya mau denger pengalaman kamu juga!


Bagikan artikel ini:

Komentar (0)

Belum ada komentar. Jadilah yang pertama memberikan tanggapan!

Tinggalkan Komentar