Merge yang salah arah, fitur yang ternyata belum siap, atau konflik yang berubah jadi rawa — semua orang pernah berada di salah satu titik itu. Kabar baiknya: Git menyediakan pintu darurat di setiap tahap, dan pintu mana yang dipakai ditentukan satu hal — seberapa jauh kesalahan itu sudah berjalan. Sebelum commit, satu perintah memulihkan segalanya. Sesudah commit tetapi sebelum dibagikan, riwayat masih boleh ditulis ulang. Sesudah dibagikan, riwayat jadi milik bersama dan pembatalan harus dibuat sebagai commit baru. Chapter ini menguji ketiganya pada repository sungguhan.

Sebelum Commit: git merge –abort #

Skenario pertama memakai kondisi paling umum: merge berhenti karena konflik, dan kita memutuskan menyerah daripada melanjutkan:

bash
mkdir latihan-batal-abort && cd latihan-batal-abort
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"
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-kontak

Output yang Dihasilkan (perintah git merge fitur-kontak):

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

Repository kini berada di keadaan setengah-merge seperti chapter Merge Conflicts . Pintu daruratnya:

bash
git merge --abort

Perintah ini tidak mencetak apa pun — diamnya adalah tanda sukses. Bukti pemulihannya dibaca dari tiga sisi:

bash
git status

Output yang Dihasilkan:

text
On branch main
nothing to commit, working tree clean
bash
cat README.md

Output yang Dihasilkan:

text
# Toko Budi

Kontak: [email protected]
bash
git log --oneline --graph --all

Output yang Dihasilkan:

text
* 040425a Ganti kontak ke tim penjualan
| * fb33553 Ganti kontak ke layanan pelanggan
|/  
* f76a000 Buat README toko

Kondisi kembali persis sebelum merge dijalankan: working tree bersih, README.md utuh versi main, main tetap di commit terakhirnya, kedua branch kembali menyimpang. Berkas internal MERGE_HEAD dan MERGE_MSG yang menandai merge berjalan ikut dihapus — git commit biasa sudah tidak akan dianggap menutup merge.

Sesudah Commit, Sebelum Dibagikan: reset ke ORIG_HEAD #

Kasus kedua lebih licik: merge berhasil tanpa konflik, commit penggabung sudah lahir, baru kemudian kita sadar penggabungan itu salah. Selama commit itu belum dibagikan ke orang lain, riwayat masih boleh disetir mundur:

bash
mkdir latihan-batal && cd latihan-batal
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf '# Situs\nberanda\n' > situs.md
git add situs.md
git commit -m "Buat halaman beranda"
git switch -c fitur-galeri
printf 'galeri-1.jpg\n' > galeri.md
git add galeri.md
git commit -m "Tambah berkas galeri"
git switch main
printf '# Situs\nberanda\ntentang\n' > situs.md
git add situs.md
git commit -m "Tambah halaman tentang"
git merge fitur-galeri -m "Gabungkan galeri"

Output yang Dihasilkan (perintah git merge fitur-galeri -m "Gabungkan galeri"):

text
Merge made by the 'ort' strategy.
 galeri.md | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 galeri.md

Di sinilah ORIG_HEAD masuk. Git menulis berkas internal .git/ORIG_HEAD setiap kali HEAD berpindah karena operasi berbahaya — merge, reset, atau rebase — mencatat posisi sebelum pindah:

bash
cat .git/ORIG_HEAD
git log --oneline -1

Output yang Dihasilkan (perintah cat .git/ORIG_HEAD):

text
ca1710efd2f10d37addf7e446cd66a041432bda0

Output yang Dihasilkan (perintah git log --oneline -1):

text
51be0f0 Gabungkan galeri

Isi ORIG_HEAD adalah ca1710e — commit “Tambah halaman tentang”, ujung main sebelum merge. Kembalikan keseluruhan branch ke titik itu:

bash
git reset --hard ORIG_HEAD

Output yang Dihasilkan:

text
HEAD is now at ca1710e Tambah halaman tentang
bash
git log --oneline --graph --all

Output yang Dihasilkan:

text
* ca1710e Tambah halaman tentang
| * 8274166 Tambah berkas galeri
|/  
* 21074d0 Buat halaman beranda

Merge commit lenyap dari riwayat main; kedua branch kembali menyimpang seolah tak pernah digabungkan. Hash pada keluaran mesin pembaca akan berbeda, polanya tetap. Jalan kedua yang setara: karena merge commit selalu satu langkah di depan ujung main semula, git reset --hard HEAD~1 juga jatuh ke titik yang sama. Kita buktikan — merge diulang sekali lagi, lalu:

bash
git reset --hard HEAD~1

Output yang Dihasilkan:

text
HEAD is now at ca1710e Tambah halaman tentang

Sesudah Dibagikan: git revert -m 1 #

Komit merge yang sudah di-push dan dipakai rekan kerja tidak boleh di-reset — menulis ulang riwayat bersama akan memutus salinan semua orang. Pembatalannya dibuat jujur di muka: satu commit baru yang membalik efek merge. Merge diulang sekali lagi, lalu:

bash
git revert -m 1 HEAD --no-edit

Output yang Dihasilkan:

text
[main 42f4573] Revert "Gabungkan galeri"
 Date: Thu Oct 15 20:50:00 2026 +0700
 1 file changed, 1 deletion(-)
 delete mode 100644 galeri.md

Flag -m 1 (mainline) wajib ada karena commit merge punya dua parent — Git harus diberi tahu sisi mana yang dianggap “jalur utama” yang dibalik. Angka 1 berarti parent pertama: sisi tempat kita berdiri saat merge (main), sesuai konvensi first-parent dari chapter Three-Way Merge . Commit baru bertajuk Revert "Gabungkan galeri" lahir di puncak riwayat:

bash
git log --oneline --graph --all

Output yang Dihasilkan:

text
* 42f4573 Revert "Gabungkan galeri"
*   361af8d Gabungkan galeri
|\  
| * 8274166 Tambah berkas galeri
* | ca1710e Tambah halaman tentang
|/  
* 21074d0 Buat halaman beranda

Baca grafnya: merge 361af8d tetap tercatat, dan di atasnya berdiri 42f4573 yang membatalkan efeknya — galeri.md hilang kembali dari working tree. Riwayat tidak disembunyikan; ia justru menceritakan keputusan beserta pembatalannya. Sesudah revert, pengembangan bisa lanjut dari titik itu. Cabang pembatalan commit secara umum — termasuk untuk commit biasa dan perdebatan kapan revert mengalahkan reset — dibahas tuntas di chapter git revert ; aturan main-main dengan riwayat bersama dirangkum di Aturan Aman Mengubah Riwayat .

Tabel Situasi ke Solusi #

SituasiPerintahHasil
Merge berjalan, konflik belum selesaigit merge --abortKeadaan kembali persis sebelum merge
Commit merge sudah dibuat, belum dibagikangit reset --hard ORIG_HEAD (atau HEAD~1)Riwayat ditulis ulang, merge hilang
Commit merge sudah dibagikangit revert -m 1 <hash-merge>Commit baru pembatal, riwayat tetap utuh

Makin lama kesalahan dibiarkan, makin panjang jalan pulangnya — dan makin besar andil orang lain di dalamnya. Dokumentasi resmi masing-masing perintah ada di git-scm.com/docs/git-merge dan git-scm.com/docs/git-revert . Setelah merge selesai dibatalkan atau justru diterima, satu tugas rumah tangga menunggu: membersihkan branch-branch yang sudah menyelesaikan tugasnya: Menghapus Branch .