Diagnosing corruption
Repositories corrupt through power loss, disk failure, partial network sync, or buggy non-Git tools touching .git. Symptoms range from "fatal: bad object" to wrong content silently delivered. Diagnosis starts with fsck:
git fsck --full
git fsck --full --strict --no-dangling
git fsck --connectivity-only
git fsck --lost-found
--lost-found writes orphaned objects to .git/lost-found/ for manual inspection.
Common failures and fixes
Loose object corrupted
If fsck reports broken link from ... to blob <sha>, see if a colleague's clone has the object:
# on healthy clone:
git cat-file -p <sha> > /tmp/recovered
# on corrupt clone:
cd .git/objects/<xx>
mv <rest-of-sha> <rest-of-sha>.bad
git hash-object -w /tmp/recovered
Pack file corrupted
Find the bad pack:
for p in .git/objects/pack/pack-*.pack; do
git verify-pack -v "$p" >/dev/null 2>&1 || echo "BAD: $p"
done
Then either remove the bad pack and refetch:
rm .git/objects/pack/pack-<sha>.{pack,idx,bitmap,rev}
git fetch --all
git repack -ad
Reflog corrupted or missing
The reflog is per-clone; cannot recover from upstream. If lost, missing branches must be reconstructed from FETCH_HEAD or by asking colleagues for their tip SHAs.
Index corrupted
rm .git/index
git reset # rebuilds index from HEAD
Refs corrupted
git pack-refs --all
cat .git/packed-refs # readable text
git update-ref refs/heads/main <sha> # recreate from known SHA
Repository-wide recovery from a clone
Often the fastest path is to clone fresh from a healthy remote, then copy local-only branches:
git clone https://example.com/repo.git fresh
cd corrupt
git push ../fresh 'refs/heads/local-only:refs/heads/local-only'
Prevention
- Run
git fsckregularly;git maintenancecan include it. - Store bare backups:
git clone --mirroron a separate disk. - Avoid editing inside
.git/by hand. - Use ECC RAM and reliable storage on long-lived servers.
Common mistakes
Running git gc on a corrupt repo — pruning may delete the only copies of recoverable objects. Always backup .git before recovery. Mixing recovered objects from different SHA-1 algorithms; SHA-256 repos cannot accept SHA-1 objects.
SHA-1 collision protection
Modern Git includes SHAttered hardening, refusing to write objects whose hashes match the known collision pair. Verify your build:
git --version
echo "test" | git hash-object --stdin
Related
See "Git garbage collection: gc, prune, and pack-refs", "Git internals: the object database", and "Repository size analysis: git count-objects and git sizer".