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:
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 reflogOutput yang Dihasilkan:
HEAD is now at 144bd69 Mulai laporan triwulanOutput yang Dihasilkan:
144bd69 HEAD@{0}: reset: moving to HEAD~1
781298a HEAD@{1}: commit: Tambah laporan inti
144bd69 HEAD@{2}: commit (initial): Mulai laporan triwulanAlamat 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:
git reflog expire --expire-unreachable=now --all
git reflogOutput yang Dihasilkan:
144bd69 HEAD@{0}: commit (initial): Mulai laporan triwulanJejaknya 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:
git fsck --lost-found
ls .git/lost-found/commitOutput yang Dihasilkan:
dangling commit 781298ac7885886d5ffb2e02f8ec59ef7782ad12Output yang Dihasilkan:
781298ac7885886d5ffb2e02f8ec59ef7782ad12Commit “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:
git show 781298aOutput yang Dihasilkan:
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 v1Kecocokannya 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 #
git branch pulihan 781298a
git log --oneline pulihanOutput yang Dihasilkan:
781298a Tambah laporan inti
144bd69 Mulai laporan triwulangit 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:
git merge pulihan
cat laporan.mdOutput yang Dihasilkan:
Updating 144bd69..781298a
Fast-forward
laporan.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 laporan.mdOutput yang Dihasilkan:
laporan v1Merge 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:
rm -rf .git/lost-foundDirektori 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:
| Skenario | Langkah pertama | Panduan |
|---|---|---|
| Commit tertelan reset, rebase, atau amend | git reflog, lalu HEAD@{n} | Memulihkan Commit |
Branch terhapus lewat -D | hash dari pesan Deleted branch, atau git reflog | Memulihkan Branch Terhapus |
| Berkas terhapus | git restore <berkas>; sudah ter-commit: git log --full-history | Memulihkan File Terhapus |
| Simpanan stash keliru ter-drop | hash dari pesan Dropped, atau git fsck --lost-found | Dangling 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:
git bundle create cadangan.bundle --allPerintah 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 .