Topic 8.2
Packfiles, Garbage Collection & Repository Health
In one line
Git stores objects loose at first, then packs them with delta compression. Garbage collection removes unreachable objects after a grace period, fsck checks integrity, and git maintenance keeps big repos fast.
Think of it like this
A warehouse where new deliveries are left as individual parcels near the door (loose objects) and, every night, similar items are packed together in labelled crates that store only the differences between near-identical items (packfiles with deltas).
Key ideas
- 01
LOOSE OBJECTS live in
.git/objects/ab/cdef…, zlib-compressed. PACKFILES (.git/objects/pack/*.pack+.idx) store many objects, with similar objects stored as DELTAS against each other. Clones and fetches transfer packfiles, which is why they're efficient. - 02
GARBAGE COLLECTION (
git gc, run automatically): repacks objects and prunes UNREACHABLE ones, but only after they're older than the reflog/prune expiry (reflog entries default to 90 days, unreachable ones 30). That grace period is what lets you recover 'lost' commits with the reflog (Phase 5). - 03
git fsckverifies object integrity and reports dangling/unreachable objects (useful for recovering orphaned work).git count-objects -vHshows repository size.git maintenance startschedules background tasks (prefetch, commit-graph, loose-objects, incremental repack) that keep large repos fast. - 04
Big-file mistakes: a large binary committed once stays in history forever, making every clone slower. Find it (
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sort -k3 -n | tail), remove it from history withgit filter-repo, and prevent it with Git LFS and pre-commit size checks (Phase 7).
Code & diagrams
git count-objects -vH # size-pack: 1.20 GiB count: 312 (loose)
git fsck --no-reflogs | head # dangling commit 4f2a… (recoverable work)
git maintenance start # schedule background optimisation
# biggest blobs in history
git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '$1=="blob"' | sort -k3 -n | tail -5Explain it without notes
Why can you usually recover a commit you 'lost' with reset --hard, even though it's no longer on any branch?
Practice
A repo takes 10 minutes to clone. Diagnose why.
Done when you can
I know how packfiles, gc, and reflog expiry interact
I can find what makes a repository large