Telapak tangan berkeringat: git reset --hard salah sasaran, branch lenyap lewat -D, atau simpanan stash ter-drop karena keliru indeks. Urutan tindakan di momen seperti itu menentukan nasib data — satu perintah pembersih yang terlanjur dijalankan mengubah “hilang sementara” menjadi hilang permanen. Perangkat pemulihannya sudah kita kuasai sepanjang section ini; tinggal urutan pemakaiannya. Chapter ini merangkainya menjadi SOP tujuh langkah dan mengujinya pada satu insiden latihan.

Langkah 1: Berhenti dan Jangan Bersih-bersih #

Reaksi paling berbahaya lahir dari niat baik: “merapikan” repository. git gc, git prune, dan git reflog expire menghapus objek tak terjangkau — status commit yang barusan “hilang”. Selama pembersih belum berjalan, objek itu masih utuh di .git/objects, ditahan minimal dua minggu oleh gc.pruneExpire, dan jejaknya dijaga reflog lebih lama lagi (Dangling Objects ). Langkah pertama kita berupa larangan: berhenti, biarkan repository apa adanya.

Langkah 2: Periksa Reflog Dulu #

Reflog mencatat setiap pergerakan HEAD — commit, reset, switch. Repository latihan-sop menyiapkan insiden latihannya: dua commit laporan, lalu yang terbaru tertelan reset:

bash
mkdir latihan-sop && cd latihan-sop
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'ringkasan v1\n' > ringkasan.md
git add ringkasan.md
git commit -m "Mulai laporan triwulan"
printf 'laporan v1\n' > laporan.md
git add laporan.md
git commit -m "Tambah laporan inti"
git reset --hard HEAD~1
git reflog

Output yang Dihasilkan:

text
HEAD is now at 144bd69 Mulai laporan triwulan

Output yang Dihasilkan:

text
144bd69 HEAD@{0}: reset: moving to HEAD~1
781298a HEAD@{1}: commit: Tambah laporan inti
144bd69 HEAD@{2}: commit (initial): Mulai laporan triwulan

Alamat commit terbuang terbaca di HEAD@{1} — hash di mesin pembaca akan berbeda. Mayoritas insiden segar selesai di langkah ini: bangkitkan dengan git branch pulihan 'HEAD@{1}', pola Memulihkan Commit . Untuk melatih keadaan terburuk, kita tuaikan entri yang menunjuk objek tak terjangkau — murni alat latihan, terlarang pada insiden sungguhan:

bash
git reflog expire --expire-unreachable=now --all
git reflog

Output yang Dihasilkan:

text
144bd69 HEAD@{0}: commit (initial): Mulai laporan triwulan

Jejaknya lenyap: baris commit: terhapus karena menunjuk objek tak terjangkau, baris reset karena berangkat darinya. Langkah 2 buntu — turun ke database objek.

Langkah 3: Pindai dengan fsck –lost-found #

Saat penunjuk dan catatan sama-sama tidak menolong, git fsck --lost-found memeriksa database objek dari luar:

bash
git fsck --lost-found
ls .git/lost-found/commit

Output yang Dihasilkan:

text
dangling commit 781298ac7885886d5ffb2e02f8ec59ef7782ad12

Output yang Dihasilkan:

text
781298ac7885886d5ffb2e02f8ec59ef7782ad12

Commit “hilang” ditemukan sebagai objek menggantung: utuh di .git/objects, hanya kehilangan penunjuk — persis diagnosis git fsck dan Dangling Objects . Flag --lost-found juga menjatuhkan temuan ke .git/lost-found/: commit menjadi berkas bernama hashnya di subdirektori commit, blob ditulis isinya ke other.

Langkah 4: Verifikasi Temuan #

Sebelum memulihkan, temuan wajib diverifikasi — hash menggantung bisa berupa commit lain: sisa eksperimen, hasil rebase, atau stash lama:

bash
git show 781298a

Output yang Dihasilkan:

text
commit 781298ac7885886d5ffb2e02f8ec59ef7782ad12
Author: Budi Santoso <[email protected]>
Date:   Sat Oct 24 12:05:00 2026 +0700

    Tambah laporan inti

diff --git a/laporan.md b/laporan.md
new file mode 100644
index 0000000..fb2bfb4
--- /dev/null
+++ b/laporan.md
@@ -0,0 +1 @@
+laporan v1

Kecocokannya tuntas: subjek, tanggal, dan diff laporan.md berisi laporan v1 — persis kerjaan yang tertelan reset. Bila fsck melaporkan banyak kandidat, periksa tiap hash sebelum memilih. Baru setelah temuan sevalid ini ref mana pun boleh disentuh.

Langkah 5: Pulihkan lewat Branch Baru #

bash
git branch pulihan 781298a
git log --oneline pulihan

Output yang Dihasilkan:

text
781298a Tambah laporan inti
144bd69 Mulai laporan triwulan

git branch tidak mencetak keluaran — buktinya dibaca dari git log: branch pulihan berdiri tepat di commit temuan. Mengapa branch, bukan git reset --hard 781298a? Reset menggeser branch kerja seketika: bila hash keliru, bencana pertama barunya ditukar bencana kedua di branch yang sama. Branch baru tidak menyentuh satu ref pun — main tetap diam, pulihan diperiksa santai sebelum diputuskan.

Langkah 6: Verifikasi Ulang dan Merge #

Hasil diuji ulang dua lapis — log sudah dibaca; kini isi dikembalikan ke branch kerja lewat merge:

bash
git merge pulihan
cat laporan.md

Output yang Dihasilkan:

text
Updating 144bd69..781298a
Fast-forward
 laporan.md | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 laporan.md

Output yang Dihasilkan:

text
laporan v1

Merge berjalan fast-forward karena main adalah leluhur pulihan: main maju ke commit pemulihan tanpa commit gabungan, dan laporan.md hadir kembali di working tree. Insiden tertutup tanpa satu ref pun digeser ke belakang.

Langkah 7: Rapikan Setelah Yakin #

Pembersihan baru aman sekarang, karena commit pemulihan sudah terjangkau dari main — git gc tidak akan menyentuhnya lagi:

bash
rm -rf .git/lost-found

Direktori fsck dibuang karena tugasnya selesai; branch pulihan boleh dihapus dengan git branch -d pulihan (sudah tergabung) atau dibiarkan sebagai penanda. Pengaturan masa hidup objek dirinci di git-gc .

Skenario Umum dan Langkah Pertamanya #

Empat insiden paling sering beserta pintu masuknya:

SkenarioLangkah pertamaPanduan
Commit tertelan reset, rebase, atau amendgit reflog, lalu HEAD@{n}Memulihkan Commit
Branch terhapus lewat -Dhash dari pesan Deleted branch, atau git reflogMemulihkan Branch Terhapus
Berkas terhapusgit restore <berkas>; sudah ter-commit: git log --full-historyMemulihkan File Terhapus
Simpanan stash keliru ter-drophash dari pesan Dropped, atau git fsck --lost-foundDangling Objects

Tiga baris atas masuk lewat jalur reflog; baris terakhir langsung jatuh ke fsck karena satu-satunya alamatnya — pesan Dropped — mudah terlewat. Setelah alamat ditemukan, semua baris lanjut ke urutan yang sama.

Diagram Alur Keputusan #

Keputusan pertama memisahkan insiden segar — reflog masih mencatat, mayoritas kasus — dari insiden tua yang turun ke fsck; keputusan kedua memisahkan “objek masih hidup” dari “harus ambil cadangan”. Semua jalur bertemu di git show dan branch baru: verifikasi dulu, pulihkan tanpa menggeser apa pun, baru merapikan.

Pencegahan: bundle Sebelum Operasi Berisiko #

SOP terbaik adalah yang jarang dipakai. Sebelum operasi yang menulis ulang riwayat — rebase besar, pembersihan riwayat, eksperimen reset — bungkus dulu keadaannya:

bash
git bundle create cadangan.bundle --all

Perintah ini senyap: seluruh refs beserta objeknya terbungkus ke satu berkas biasa, siap jadi sumber pemulihan lewat clone atau fetch — mekanismenya dibahas di Backup Repository , pola pra-operasinya dipraktikkan di Aturan Aman Mengubah Riwayat .

Perangkat pemulihan lengkap: reflog untuk insiden segar, fsck untuk yang tua, cadangan untuk skenario terburuk, dan SOP tujuh langkah yang menjaga urutannya. Perjalanan berikutnya berpaling ke merayakan yang berhasil: menandai titik rilis dengan nama yang mudah diingat, dibuka di section Tags dan Releases .