Setiap operasi yang menulis ulang riwayat — reset --hard, commit --amend, git branch -D, sampai rebase
— meninggalkan mayat: objek lama yang kehilangan seluruh penunjuknya namun tetap utuh di .git/objects. Objek dangling itulah sisa operasi yang belum dibersihkan, dan justru karena Git menahannya beberapa lama sebelum dihapus, mayat-mayat itu bisa dibangkitkan. git fsck
sudah mengenalkan temuan dangling commit; chapter ini menjalankan jalur penyelamatnya ujung-ke-ujung: sebuah commit “hilang” akibat rebase, reflog-nya sengaja kita tuaikan, lalu fsck menjadi satu-satunya detektor — temuan, verifikasi, dan pemulihan lengkap dengan branch baru.
Membuat Commit “Hilang” lewat Rebase #
Repository latihan-dangling menyiapkan cerita klasiknya: branch fitur berangkat dari commit kedua, sementara main berjalan duluan, lalu fitur di-rebase agar berdiri di ujung main:
mkdir latihan-dangling && cd latihan-dangling
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'beranda\n' > situs.md
git add situs.md
git commit -m "Buat halaman beranda"
printf 'beranda\nfaq\n' > situs.md
git add situs.md
git commit -m "Tambah halaman faq"
git switch -c fitur
printf 'galeri v1\n' > galeri.md
git add galeri.md
git commit -m "Mulai halaman galeri"
git switch main
printf 'kontak v1\n' > kontak.md
git add kontak.md
git commit -m "Tambah halaman kontak"
git switch fitur
git rebase main
git log --oneline -2 fiturOutput yang Dihasilkan:
Successfully rebased and updated refs/heads/fitur.Output yang Dihasilkan:
74102f2 Mulai halaman galeri
2ad3a53 Tambah halaman kontakRebase sukses dan riwayat fitur tampak normal — tapi perhatikan hashnya: Mulai halaman galeri kini bernomor 74102f2. Commit aslinya yang dulu dibuat di atas Tambah halaman faq tidak lagi dirujuk fitur — hash di mesin pembaca akan berbeda. Dari sudut pandang branch, commit lama itu sudah “hilang”.
Jaring Pertama: Reflog — dan Saat Jaring Itu Menipis #
Jaring penyelamat pertama tetap reflog
: perjalanan fitur terekam lengkap,
git reflog show fiturOutput yang Dihasilkan:
74102f2 fitur@{0}: rebase (finish): refs/heads/fitur onto 2ad3a53e09f48029f64d4a83dac6a69f28c59371
fd76e17 fitur@{1}: commit: Mulai halaman galeri
272ea05 fitur@{2}: branch: Created from HEADBaris fitur@{1} masih menyimpan alamat commit asli: fd76e17. Namun entri reflog tidak abadi — Git secara berkala menghapus entri lama. Kita percepat proses itu untuk melihat keadaan “insiden berumur lebih dari sebulan”, lalu periksa jaringnya lagi:
git reflog expire --expire-unreachable=now --all
git reflog show fiturOutput yang Dihasilkan:
272ea05 fitur@{0}: branch: Created from HEADDua entri lenyap sekaligus: commit: Mulai halaman galeri (menunjuk objek tak terjangkau) dan rebase (finish) (berangkat dari objek tak terjangkau). Sisa reflog fitur hanya mencatat penciptaan branch — alamat fd76e17 resmi lenyap dari tempat terakhirnya.
Jalur Penyelamat: fsck → show → branch #
Inilah momen fsck menjadi pahlawan. Database objek masih memuat segalanya:
git fsckOutput yang Dihasilkan:
dangling commit fd76e1713a3e2f4de61a3457554dd963d16db254git fsck --unreachableOutput yang Dihasilkan:
unreachable tree e4f90c64b685b3194738b945c21d7ba98e3c342e
unreachable commit fd76e1713a3e2f4de61a3457554dd963d16db254Perbandingan dua keluaran itu merangkum kembali beda dangling dan unreachable
: commit fd76e17 adalah ujung rantai yang menggantung, sementara tree snapshot-nya e4f90c6 tak terjangkau tapi masih dirujuk commit itu. Blob galeri.md tidak muncul sama sekali — isi berkasnya identik, sehingga commit hasil rebase memakai ulang blob yang sama dan objeknya tetap terjangkau. Langkah verifikasi wajib sebelum memulihkan apa pun:
git show fd76e17Output yang Dihasilkan:
commit fd76e1713a3e2f4de61a3457554dd963d16db254
Author: Budi Santoso <[email protected]>
Date: Sat Oct 24 10:35:00 2026 +0700
Mulai halaman galeri
diff --git a/galeri.md b/galeri.md
new file mode 100644
index 0000000..8581b10
--- /dev/null
+++ b/galeri.md
@@ -0,0 +1 @@
+galeri v1Isinya utuh: commit asli beserta berkas galeri.md yang dibuatnya. Pulihkan dengan branch baru — bukan reset — agar tidak satu pun ref yang digeser:
git branch pulihan fd76e17
git log --oneline pulihanOutput yang Dihasilkan:
fd76e17 Mulai halaman galeri
272ea05 Tambah halaman faq
016e8f4 Buat halaman berandaCommit “hilang” resmi bangkit sebagai branch pulihan. Riwayatnya memperlihatkan garis waktu lama — Tambah halaman faq tanpa Tambah halaman kontak — sesuai basis ketika commit itu dibuat. Perintah git branch tidak mencetak keluaran; bukti keberhasilannya memang dibaca dari git log.
Masa Hidup Objek Menggantung #
Seberapa lama jendela penyelamatan ini terbuka? Git menjawabnya lewat tiga pengaturan dengan nilai bawaan berikut:
| Pengaturan | Nilai bawaan | Efek |
|---|---|---|
gc.pruneExpire | 2 minggu | objek lepas lebih tua dari dua minggu boleh dihapus oleh git gc |
gc.reflogExpireUnreachable | 30 hari | entri reflog yang menunjuk objek tak terjangkau dihapus setelah sebulan |
gc.reflogExpire | 90 hari | entri reflog HEAD dan branch lokal dihapus setelah tiga bulan |
Tabel ini adalah tabel garansi waktu: selama objek berumur kurang dari dua minggu, git gc menahannya apa pun yang terjadi; reflog umumnya menjaga lebih lama lagi. Sebaliknya, commit yang “hilang” setahun lalu tanpa cadangan berada di luar garansi — objeknya boleh sudah terhapus. Detail mekanisme pembersihannya dibahas di Garbage Collection
, sementara rujukan pengaturannya ada di git-gc
.
Semua senjata darurat kini terkumpul — tapi masih ada satu lapis pertahanan yang lebih baik daripada pemulihan terbaik: mencegah data benar-benar hilang dengan cadangan. Git menyediakan dua jalur resminya, clone --mirror dan git bundle, yang dibahas di Backup Repository
.