git reset --hard HEAD~2 adalah perintah yang terasa seperti tombol hapus permanen: dua commit lenyap dari git log, isi berkasnya ikut hilang dari working tree, dan terminal tidak menyisakan petunjuk. Nyatanya commit yang “terhapus” itu masih utuh di dalam database objek Git — yang hilang hanyalah penunjuk menujunya, dan reflog
menyimpan salinan penunjuk tersebut. Chapter ini memutar ulang skenario terburuk itu langkah demi langkah: menyimpan hash sebelum kejadian, “kehilangan” commit, menemukannya kembali di reflog, lalu memulihkannya lewat dua jalur — branch baru dan reset balik.
Skenario: reset –hard yang Menelan Dua Commit #
Repository latihan latihan-commit diisi tiga commit berurutan. Sebelum melakukan apa pun yang berisiko, hash posisi terkini disimpan ke sebuah berkas — kebiasaan sederhana yang berfungsi seperti catatan asuransi:
mkdir latihan-commit && cd latihan-commit
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'laporan v1\n' > laporan.md
git add laporan.md
git commit -m "Tulis laporan v1"
printf 'laporan v2\n' > laporan.md
git add laporan.md
git commit -m "Perbaiki laporan"
printf 'ringkasan singkat\n' > ringkasan.md
git add ringkasan.md
git commit -m "Tambah ringkasan"
git rev-parse HEAD > hash.txt
git log --onelineOutput yang Dihasilkan:
770b670 Tambah ringkasan
9226799 Perbaiki laporan
a2f06c7 Tulis laporan v1Kondisi awalnya aman dan tercatat. Isi berkas simpanannya satu baris hash penuh:
cat hash.txtOutput yang Dihasilkan:
770b670e18cefbcb9cddef2ea4e391b8e00e0b7bSekarang kecelakaannya — seolah-olah kita salah mengetik rentang reset dua commit terlalu jauh:
git reset --hard HEAD~2Output yang Dihasilkan:
HEAD is now at a2f06c7 Tulis laporan v1git log --onelineOutput yang Dihasilkan:
a2f06c7 Tulis laporan v1git log kini hanya menampilkan “Tulis laporan v1”. Dua commit teratas — “Perbaiki laporan” dan “Tambah ringkasan” — seolah tidak pernah dibuat.
Mencari Jejak di reflog #
Inilah momen reflog menunjukkan fungsinya. Setiap commit yang barusan “lenyap” masih tercatat sebagai posisi HEAD yang pernah dicapai:
git reflogOutput yang Dihasilkan:
a2f06c7 HEAD@{0}: reset: moving to HEAD~2
770b670 HEAD@{1}: commit: Tambah ringkasan
9226799 HEAD@{2}: commit: Perbaiki laporan
a2f06c7 HEAD@{3}: commit (initial): Tulis laporan v1Dua baris teratas adalah kartu nama para “korban”: HEAD@{1} menunjuk commit “Tambah ringkasan” dan HEAD@{2} menunjuk “Perbaiki laporan”. Kedua commit itu tidak pernah keluar dari database — kita bisa membuktikannya langsung dengan menanyakan tipe objeknya memakai hash yang tersimpan di hash.txt:
git cat-file -t $(cat hash.txt)Output yang Dihasilkan:
commitGit menjawab commit: objeknya masih hidup, utuh, dan bisa dibaca isinya kapan pun. Hash pada keluaran di atas milik mesin uji; di mesin pembaca hash akan berbeda, tetapi jawaban commit tetap sama.
Jalur Pertama: Memulihkan dengan branch Baru #
Cara paling aman memberi commit “hilang” sebuah rumah baru adalah membuat branch yang menunjuk langsung ke posisinya. Kita pakai hash dari berkas simpanan — HEAD@{1} akan bekerja sama persis:
git branch pulihan $(cat hash.txt)
git log --oneline pulihanOutput yang Dihasilkan:
770b670 Tambah ringkasan
9226799 Perbaiki laporan
a2f06c7 Tulis laporan v1Ketiga commit tampil utuh di branch pulihan. Peta akhirnya terlihat jelas:
git log --oneline --graph --allOutput yang Dihasilkan:
* 770b670 Tambah ringkasan
* 9226799 Perbaiki laporan
* a2f06c7 Tulis laporan v1main dan pulihan berbagi rantai yang sama; tidak satu byte pekerjaan yang hilang. Pendekatan branch baru punya satu kelebihan penting: main tidak disentuh sama sekali — kita bisa memeriksa isi pulihan dengan tenang sebelum memutuskan langkah berikutnya.
Jalur Kedua: Memulihkan dengan reset –hard #
Bila yang kita inginkan sederhana — mengembalikan main persis ke posisi sebelum kecelakaan — git reset --hard bisa diarahkan ke hash yang sama:
git reset --hard $(cat hash.txt)Output yang Dihasilkan:
HEAD is now at 770b670 Tambah ringkasangit log --onelineOutput yang Dihasilkan:
770b670 Tambah ringkasan
9226799 Perbaiki laporan
a2f06c7 Tulis laporan v1Riwayat main kembali menampilkan ketiga commit. Kedua jalur tadi bisa diringkas begini:
| Aspek | git branch pulihan <hash> | git reset --hard <hash> |
|---|---|---|
| Branch asal | Tidak tersentuh | Langsung digeser ke posisi lama |
| Ruang gerak setelahnya | Bisa diperiksa dulu, digabung bila cocok | Keputusan langsung final |
| Risiko bila salah pilih hash | Hampir nol — hanya lahir branch baru | main pindah lagi (tetap bisa diulang dari reflog) |
Mengapa Commit Berhasil Bertahan #
Kunci pemulihan ini ada pada cara Git menyimpan data: commit adalah objek di .git/objects/ yang tetap ada selama masih direferensikan — oleh branch, tag, atau reflog — dan masih diberi masa tenggang setelah kehilangan semua rujukan. Pengaturan gc.reflogExpireUnreachable (default 30 hari) menjaga entri reflog yang commit-nya sudah tak terjangkau; pembersihan permanen baru terjadi ketika git gc menghapus objek yang sudah tidak dirujuk siapa-siapa. Itulah sebabnya kalimat berikut layak dihafal: hampir tidak ada yang benar-benar hilang di Git — yang biasanya hilang hanyalah penunjuknya.
Dokumentasi perilaku reset --hard tersedia di git-reset
. Commit yang tertelan reset kini bisa dipulihkan dengan mata terpejam — berikutnya kita naik satu tingkat: memulihkan branch utuh yang terhapus, beserta seluruh riwayatnya, di Memulihkan Branch Terhapus
.