Sebelas chapter silam kita membedah mesin dalam Git sampai ke byte-nya: object model, refs, packfile, hingga penjadwalan maintenance. Chapter penutup ini membalik arah pandang — bukan lagi “bagaimana mesin bekerja”, melainkan “bagaimana membaca kondisinya saat mesin terasa sakit”. Gejalanya selalu datang lebih dulu daripada diagnosa: clone yang makin lama, git status yang makin berat, .git yang membengkak tanpa sebab. Kotak peralatannya murni bawaan Git — git count-objects, git verify-pack, git fsck — dan semuanya sudah kita temui di sepanjang section; kini ketiganya dirangkai menjadi alur diagnosa utuh dan diuji pada repository yang sengaja dibuat sakit.

Repository “Sakit” sebagai Bahan Uji #

Bahan uji kita meniru proyek yang tumbuh tanpa perawatan: 600 berkas kecil diimpor sekali, lalu 40 batch revisi yang masing-masing menyentuh 15 berkas. Totalnya 41 commit — cukup untuk menimbuni objects/ dengan objek lepas:

bash
mkdir latihan-diag && cd latihan-diag
git init -b main
git config user.name "Budi Santoso"
git config user.email "[email protected]"
mkdir src
for i in $(seq 1 600); do printf "data %d versi awal\nbaris %d\n" "$i" "$i" > "src/data-$i.txt"; done
git add .
git commit -m "Impor 600 data"
for c in $(seq 1 40); do
  for k in $(seq $(( (c-1)*15+1 )) $(( (c-1)*15+15 ))); do
    printf "data %d versi %d\nbaris %d\n" "$k" "$c" "$k" > "src/data-$k.txt"
  done
  git add -u
  git commit -m "Revisi 15 data batch $c"
done

Pemeriksaan pertama selalu palang angka — flag -vH mencetak seluruh statistik dengan satuan yang mudah dibaca manusia:

bash
git count-objects -vH

Output yang Dihasilkan:

text
count: 1323
size: 5.65 MiB
in-pack: 0
packs: 0
size-pack: 0 bytes
prune-packable: 0
garbage: 0
size-garbage: 0 bytes

Dua ukuran pendamping:

bash
du -sh .git
time git status

Output yang Dihasilkan:

text
6.9M	.git
text
On branch main
nothing to commit, working tree clean

real	0m0.003s
user	0m0.001s
sys	0m0.002s

Bedah count-objects: Delapan Angka Diagnosis #

Keluaran itu adalah denyut database objek. Setiap field menjawab pertanyaan diagnosis yang berbeda:

FieldArtiBacaan diagnosis
countjumlah objek lepas — berkas individual di objects/xx/ribuan berarti gc belum pernah (atau jarang) berjalan
sizeruang disk objek lepaspembanding besaran sebelum-sesudah perawatan
in-packjumlah objek di dalam packcermin count; idealnya dominan setelah gc
packsjumlah berkas packmenumpuk = panggil incremental-repack atau gc
size-packruang disk seluruh packukuran yang sesungguhnya dipindah saat clone dan fetch
prune-packableobjek lepas yang isinya juga sudah ada di packdobel simpan — aman dibersihkan git prune-packed
garbageberkas di objects/ yang bukan objek valid bukan pula packjejak operasi terputus; layak diselidiki, bukan diabaikan
size-garbageruang disk berkas sampah itumengukur seberapa banyak “puing” menumpuk

Kondisi repository kita terbaca dari baris pertama: count: 1323 dan in-pack: 0 — 1323 berkas kecil (600 blob versi awal, 600 blob revisi, 82 tree, 41 commit) tak pernah dikemas, memakan 5,65 MiB dan ribuan operasi buka-berkas tiap kali riwayat ditelusuri. Catat juga time git status yang tetap 0,003 detik — fakta yang kita konfirmasi belakangan: status membaca working directory, bukan database objek, sehingga objek lepas tidak membuatnya lambat.

fsck –full –strict: Integritas dan Objek Menggantung #

Pemeriksaan kedua menagih kesehatan. git fsck menelusuri rantai referensi antar objek; --full memeriksa seluruh objek (bukan hanya yang dirujuk), --strict menaikkan standar validitas format. Kita uji dengan sengaja menyuntikkan satu blob tak terjangkau:

bash
printf 'cepat-hilang\n' | git hash-object -w --stdin

Output yang Dihasilkan:

text
0b3bccde3af1ca737a170f9a7d94d96314a10cb7
bash
git fsck --full --strict

Output yang Dihasilkan:

text
dangling blob 0b3bccde3af1ca737a170f9a7d94d96314a10cb7

Blob itu ditulis ke objects/ namun tak dirujuk siapa pun — fsck melaporkannya sebagai dangling (hash berbeda di mesin pembaca). Temuan ini bukan galat: keluaran kosong dengan kode exit 0 berarti repository bersih; dangling hanya laporan objek tak terjangkau yang masih bisa dipulihkan. Varian fsck lain beserta arti tiap temuan dibedah tuntas di git fsck .

Perawatan: gc dan Tabel Sebelum-Sesudah #

Sekarang pengobatan — git gc senyap tanpa keluaran — lalu ukur ulang semua parameter:

bash
git gc
git count-objects -vH

Output yang Dihasilkan:

text
count: 0
size: 0 bytes
in-pack: 1324
packs: 2
size-pack: 133.83 KiB
prune-packable: 0
garbage: 0
size-garbage: 0 bytes
bash
du -sh .git
ls .git/objects/pack/
time git status

Output yang Dihasilkan:

text
376K	.git
text
pack-03ec2c71f18a258ce49cebd89dfb33c5bc16554a.idx
pack-03ec2c71f18a258ce49cebd89dfb33c5bc16554a.mtimes
pack-03ec2c71f18a258ce49cebd89dfb33c5bc16554a.pack
pack-03ec2c71f18a258ce49cebd89dfb33c5bc16554a.rev
pack-8f1ae6adcce6b2a7d47481f73b924ecac45ea5c2.idx
pack-8f1ae6adcce6b2a7d47481f73b924ecac45ea5c2.pack
pack-8f1ae6adcce6b2a7d47481f73b924ecac45ea5c2.rev
text
On branch main
nothing to commit, working tree clean

real	0m0.004s
user	0m0.000s
sys	0m0.004s
UkuranSebelum gcSesudah gc
Objek lepas (count)13230
Objek di pack (in-pack)01324
Ruang objek lepas (size)5,65 MiB0 bytes
Ukuran pack (size-pack)0 bytes133,83 KiB
Jumlah pack (packs)02
Ukuran .git6,9M376K
time git status0m0,003s0m0,004s

Tiga temuan dari tabel itu. Pertama, 1323 objek lepas menjadi nol dan seluruh 1324 objek (termasuk blob suntikan) berpindah ke pack — kompresi delta memeras 5,65 MiB isi objek menjadi 133,83 KiB, dan du turun dari 6,9M ke 376K karena ribuan berkas kecil menjadi sedikit berkas besar. Kedua, ada dua pack: pack kedua yang berpasangan dengan berkas .mtimes adalah cruft pack — penampungan objek tak terjangkau yang masih muda beserta catatan umurnya, persis mekanisme masa tenggang dari Garbage Collection . Nama pack-<hash> dihitung dari isi pack, jadi nilainya berbeda antar eksekusi repack. Itulah sebabnya fsck masih menemukan blob yang sama setelah gc; bukti terakhirnya:

bash
git fsck --full --strict

Output yang Dihasilkan:

text
dangling blob 0b3bccde3af1ca737a170f9a7d94d96314a10cb7

Blob muda itu masih ditahan. Bila isinya ingin diperiksa dulu, git fsck --lost-found menyalin objek menggantung ke .git/lost-found/ agar bisa dibaca git cat-file:

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

Output yang Dihasilkan:

text
dangling blob 0b3bccde3af1ca737a170f9a7d94d96314a10cb7
0b3bccde3af1ca737a170f9a7d94d96314a10cb7

Berkas kedua adalah salinan blob itu di lost-found/other/. Setelah yakin tidak ada yang ingin dipulihkan, pembersihan final:

bash
git gc --prune=now
git fsck --full --strict

gc berjalan senyap; fsck yang kedua tidak mencetak apa pun dan keluar 0 — repository bersih dari objek menggantung.

verify-pack -s: Kondisi Rantai Delta #

Pemeriksaan ketiga membaca isi pack. git verify-pack memvalidasi setiap objek di dalamnya; flag -s hanya mencetak statistik rantai delta:

bash
git verify-pack -s .git/objects/pack/pack-*.idx

Output yang Dihasilkan:

text
non delta: 1 object
non delta: 1284 objects
chain length = 1: 2 objects
chain length = 2: 2 objects
chain length = 3: 2 objects
chain length = 4: 2 objects
chain length = 5: 2 objects
chain length = 6: 2 objects
chain length = 7: 2 objects
chain length = 8: 2 objects
chain length = 9: 2 objects
chain length = 10: 2 objects
chain length = 11: 2 objects
chain length = 12: 2 objects
chain length = 13: 2 objects
chain length = 14: 2 objects
chain length = 15: 2 objects
chain length = 16: 2 objects
chain length = 17: 1 object
chain length = 18: 1 object
chain length = 19: 1 object
chain length = 20: 1 object
chain length = 21: 1 object
chain length = 22: 1 object
chain length = 23: 1 object

Dua baris non delta muncul karena ada dua pack: cruft pack berisi satu blob (baris pertama), pack utama berisi 1284 objek utuh. Sisanya 39 objek delta yang membentuk rantai terpanjang 23 — masih jauh di bawah batas pack.depth 50, dan tiap kolom verify-pack sudah dibedah di Packfiles . Angka rantai bisa berbeda tipis antar eksekusi repack — Git menghitung ulang pemilihan delta tiap kali mengemas. Bacaan diagnosisnya: pack ini sehat. Yang mencurigakan justru kebalikannya — non delta dominan padahal isinya banyak revisi serupa (delta tak terbentuk), atau pack menumpuk puluhan berkas; dua-duanya isyarat repack.

Alur Diagnosa Repository Lambat #

Ketiga alat itu kini dirangkai. Langkah nol sebelum menuduh database objek: pastikan working directory bersih — draf dan perubahan menumpuk juga membuat status berat:

bash
printf 'data 7 versi baru\nbaris 7\n' > src/data-7.txt
printf 'laporan belum dicatat\n' > laporan-baru.md
git status --porcelain

Output yang Dihasilkan:

text
 M src/data-7.txt
?? laporan-baru.md

Format --porcelain menjawab kilat: satu berkas termodifikasi ( M) dan satu draf tak terlacak (??). Setelah working tree bersih dan keluhan berlanjut, alurnya:

Setiap percabanan punya obat yang sudah kita kuasai: objek lepas menumpuk ditangani git gc dan git maintenance ; status lambat adalah ranah core.fsmonitor dan core.untrackedCache di Repository Performance ; log dan diff yang lambat dijawab commit-graph; pack yang boros direpack seperti di Packfiles ; dan sisa terakhir — berkas besar di riwayat — berujung di File Besar .

Penutup Section: Mesin yang Dikenal #

Dari Object Model sampai chapter ini, satu benang merah menarik seluruh section: tidak ada sihir di dalam Git. Setiap keluhan — bengkak, lambat, objek hilang — selalu bisa dijatuhkan menjadi angka count-objects, rantai delta verify-pack, atau temuan fsck, lalu dijawab dengan perintah yang mekanismenya kita pahami. Itulah arti kenali mesin dalam: bukan untuk menulis ulang Git, melainkan untuk tidak pernah lagi menebak-nebak saat repository berperilaku aneh. Pemahaman ini paling terasa justru di pekerjaan paling biasa — commit harian, branch, merge, rilis — tempat keputusan seperti kapan gc atau kapan memindahkan berkas ke LFS diambil dari bukti. Section berikutnya mengarahkan seluruh bekal itu ke praktik sehari-hari: Praktik Workflow , dimulai dari workflow satu orang di Workflow Proyek Pribadi . Rujukan lengkap ketiga alat utama chapter ini: dokumentasi git-count-objects dan dokumentasi git-verify-pack .