Reflog menolong saat kita tahu apa yang dicari — hash pernah tercatat, tinggal dibaca kembali. Namun bagaimana bila kecelakaan terjadi tanpa jejak: reflog sudah kedaluwarsa, branch terhapus tanpa alamat, atau kita sekadar ingin memeriksa kesehatan repository secara menyeluruh? Untuk itu ada git fsck — singkatan file system check — yang memeriksa database objek dari luar: memverifikasi rantai referensi antar objek, mencari objek yang menggantung, dan melaporkan objek yang hilang. Chapter ini menjalankan pemeriksaan itu pada repository sehat, sengaja memproduksi objek menggantung, bahkan merusak satu objek untuk melihat keluaran missing, lalu memetakan arti setiap temuan.

Repository Sehat: Keluaran Kosong adalah Kabar Baik #

Karena git fsck tidak mengubah apa pun, ia aman dijalankan kapan saja. Repository latihan-fsck menyiapkan dua commit, lalu commit terakhir dibuang dengan reset --hard — bencana kecil yang sudah biasa kita tangani lewat reflog :

bash
mkdir latihan-fsck && cd latihan-fsck
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'catatan v1\n' > catatan.md
git add catatan.md
git commit -m "Mulai catatan proyek"
printf 'catatan v2\n' > catatan.md
git add catatan.md
git commit -m "Perluas catatan"
git fsck
git reset --hard HEAD~1
git fsck

Output yang Dihasilkan:

text
HEAD is now at 82eb244 Mulai catatan proyek

Dua kali git fsck pada blok di atas sama-sama berlalu tanpa mencetak satu baris pun — dan justru itu kabar baiknya: fsck pada repository sehat diam. Kejutan justru di pembandingnya: sehabis reset --hard, commit Perluas catatan sudah tidak terjangkau dari main, tetapi fsck tetap diam. Penjelasannya ada pada opsi bawaan fsck — git fsck -h menyebutnya --[no-]reflogs: make reflogs head nodes (default). Seluruh reflog diperlakukan sebagai akar perhitungan, dan commit yang dibuang reset masih tercatat rapi di HEAD@{1} sehingga dianggap selamat.

Menyingkap Objek Menggantung dengan –no-reflogs #

Untuk melihat dunia seolah-olah reflog sudah tidak ada — keadaan sebenarnya setelah entri kedaluwarsa — fsck diberi flag --no-reflogs:

bash
git fsck --no-reflogs

Output yang Dihasilkan:

text
dangling commit de975ba2b7917505575e43329fa0439c24515fd6

Baru sekarang “korban” kelihatan: dangling commit de975ba... — commit yang tidak terjangkau dari ref mana pun dan tidak dirujuk objek lain, padahal isinya masih utuh di database objek. Hash di mesin pembaca akan berbeda. Temuan semacam ini persis yang dijadikan titik awal penyelamatan di Dangling Objects .

Bedah Temuan: unreachable Bukan dangling #

Rasa penasaran berikutnya wajar: kalau commit itu tidak terjangkau, bagaimana dengan tree dan blob isinya? Flag --unreachable membuka daftar lengkapnya:

bash
git fsck --no-reflogs --unreachable

Output yang Dihasilkan:

text
unreachable blob ab8380179c4f6fa8d6c6bffaeb898c64b4798427
unreachable tree 3d33dd50d2b8c2850bc2378ff4663834cdc0a051
unreachable commit de975ba2b7917505575e43329fa0439c24515fd6

Perbandingannya membidahkan konsep dua istilah yang sering tertukar. unreachable mencakup semua objek tak terjangkau: commit de975ba, tree snapshot-nya 3d33dd5, hingga blob catatan v2 ab83801. Adapun dangling — temuan bawaan fsck — hanya memuat objek yang tidak dirujuk oleh objek tak terjangkau lain: tree dirujuk commit, blob dirujuk tree, sehingga satu-satunya ujung rantai yang benar-benar menggantung adalah commitnya. Setiap objek dangling pasti unreachable, tetapi tidak sebaliknya.

Temuan yang Menandakan Kerusakan: missing #

Skenario terakhir memperlihatkan temuan yang kelasnya berbeda — objek yang dirujuk tapi berkasnya hilang. Repository latihan-fsck-rusak sengaja dihapus satu objek blob-nya dari .git/objects:

bash
cd ..
mkdir latihan-fsck-rusak && cd latihan-fsck-rusak
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
printf 'harga kopi: 1000\n' > harga.md
git add harga.md
git commit -m "Buat daftar harga"
BLOB=$(git rev-parse HEAD:harga.md)
rm ".git/objects/${BLOB:0:2}/${BLOB:2}"
git fsck
git fsck --full

Output yang Dihasilkan:

text
missing blob 51d31de46e702dbe7beaf70de2383d595a61a01c

Output yang Dihasilkan:

text
missing blob 51d31de46e702dbe7beaf70de2383d595a61a01c

Perintah kedua memakai --full, yang memeriksa juga isi packfile dan object database alternat — pada repository kecil berobjek lepas seperti ini hasilnya identik. Perhatikan pula bahwa kedua perintah fsck di atas diakhiri kode keluar 2, bukan nol; skrip otomatis dapat memanfaatkan kode ini untuk mendeteksi kerusakan sejak dini.

Ringkasan arti tiap temuan:

TemuanArtiTindakan
dangling commitcommit utuh tanpa penunjuk — sisa reset, amend, rebase, atau stash dropperiksa git show <hash>, pulihkan dengan branch baru
dangling blob / dangling treeisi snapshot tak terpakai — sisa proses internalumumnya diabaikan, bisa merujuk isi versi lama
missing <objek>objek dirujuk tapi berkasnya hilangpulihkan dari cadangan — Backup Repository
unreachable <objek>tak terjangkau dari refs (superset dangling)daftar lengkap kandidat pembersihan

fsck Tidak Memperbaiki Apa Pun #

Satu hal penting dari seluruh demo di atas: fsck tidak pernah menyentuh satu objek pun. Ia murni alat diagnostik — memeriksa, melaporkan, lalu selesai. Filosofi Git di baliknya sederhana: objek tidak pernah “diperbaiki”, melainkan diberi penunjuk baru (branch, git stash apply <hash>) bila isinya berharga, atau dibiarkan sampai pembersihan rutin menghapusnya. Proses pembersih itu sendiri adalah tugas git gc, yang membahas masa hidup objek menggantung secara mendalam di Garbage Collection . Rujukan opsi lengkap fsck tersedia di git-fsck .

Kini temuan dangling commit <hash> bukan lagi teka-teki. Bab berikutnya menjalankan jalur penyelamatnya dari awal sampai akhir: commit “hilang” akibat rebase ditemukan lewat fsck, diverifikasi dengan git show, lalu dibangkitkan sebagai branch — ujung-ke-ujung di Dangling Objects .