Overview
The error “fatal: loose object <sha> (stored in .git/objects/xx/…) is corrupt” means a file in your repository’s object database failed integrity checks. Git stores objects either as loose files under .git/objects or inside packfiles. Corruption typically comes from disk errors, abrupt process termination, antivirus interference, or flaky network/CI caches.
Key idea: If a good remote exists, the fastest, safest fix is to reclone. If not, determine whether the bad object is unreachable (safe to prune) or reachable (must be recovered from another source).
Quickstart (safest path)
- Back up your working directory before any destructive steps.
- If you have a healthy remote:
- Move your current repo aside.
- Fresh-clone from the remote.
- Reapply uncommitted changes if needed.
Example:
# 1) Back up any uncommitted changes
mkdir -p ../repo_backup
rsync -a --exclude='.git' . ../repo_backup/
# 2) Move the broken repo aside and reclone
cd ..
mv myrepo myrepo_broken
git clone --recursive [email protected]:org/myrepo.git myrepo
# 3) Reapply local changes if needed
rsync -a --ignore-existing myrepo_backup/ myrepo/
If you cannot reclone, see the step-by-step fixes below.
Minimal working example (simulate and fix)
This demo creates a healthy bare remote, clones it, corrupts one object locally, shows the error, and fixes by recloning. It’s self-contained and safe to run in a temp directory.
#!/usr/bin/env bash
set -euo pipefail
# Setup a bare "remote" and a working clone
rm -rf demo_origin.git demo_work
git init --bare demo_origin.git
git clone demo_origin.git demo_work
pushd demo_work
echo hello > file.txt
git add file.txt
git commit -m "init"
git push origin HEAD:main
popd
# Fresh clone as our working repo
rm -rf demo_work
git clone demo_origin.git demo_work
pushd demo_work
# Find the blob SHA and corrupt its loose object (force loose by unpacking)
git repack -A -d # ensure clean packs
# Write a new blob as loose
printf "world\n" > tmp.txt
blob_sha=$(git hash-object -w tmp.txt)
# Corrupt it
dir=${blob_sha:0:2}; file=${blob_sha:2}
truncate -s 1 .git/objects/$dir/$file || true
# fsck reports corruption
set +e
git fsck --full || true
set -e
# Fix by recloning (recommended)
popd
rm -rf demo_work
git clone demo_origin.git demo_work
echo "Recovered by recloning."
Notes:
- In real repos, the corrupt object may be a blob, tree, commit, or tag. If it’s reachable from current refs, you must recover it from a healthy source.
Diagnosis and repair (step-by-step)
- Back up first
- Copy your working directory (excluding .git if you plan to reclone), or create a whole-directory backup.
- Verify and identify the object
- Run a full check and note the SHA and path:
git fsck --full
# Example output: error: object <sha> is corrupt at .git/objects/xx/<rest>
- Quickly check reachability:
git fsck --no-reflogs --full | grep -E "dangling|missing" || true
- If the object is unreachable (dangling)
- Safe path: prune unreachable loose objects.
git gc --prune=now
# Or more direct:
# git prune --expire now
# Verify again
git fsck --full
- If the object is reachable and you have a healthy remote
- Best fix: reclone as in Quickstart.
- Alternative when reclone is not feasible (e.g., large monorepo, slow network): replace only the .git directory from a fresh clone.
# In parent dir
git clone --no-checkout [email protected]:org/myrepo.git myrepo_clean
rsync -a --delete myrepo_clean/.git/ myrepo/.git/
rm -rf myrepo_clean
# Restore working tree to your branch
cd myrepo
git checkout -f main
- If the object is reachable and no remote exists, but another good clone or backup does
- Copy the missing/corrupt object from the good clone:
# On healthy clone
sha=<the_corrupt_sha>
dir=${sha:0:2}; file=${sha:2}
scp .git/objects/$dir/$file user@brokenhost:/path/to/repo/.git/objects/$dir/
# Then on broken repo
cd /path/to/repo
git fsck --full
- Last-resort local repair when remote exists but you must avoid full reclone
- This is riskier and may not always succeed due to fetch negotiation:
sha=<the_corrupt_sha>
# Remove the corrupt file so it’s clearly missing
rm -f .git/objects/${sha:0:2}/${sha:2}
# Temporarily move the branch ref so the remote will resend history
branch=$(git rev-parse --abbrev-ref HEAD)
git update-ref -d refs/heads/$branch
# Re-fetch and reset to the remote tip
git fetch origin
git checkout -B $branch origin/$branch
# Verify
git fsck --full
If verification still fails or multiple objects are affected, reclone.
Common scenarios and recommended actions
| Scenario | Action |
|---|---|
| CI cache corruption | Delete cache and reclone before build; validate with git fsck. |
| Dangling loose objects only | git gc --prune=now to remove them. |
| Reachable object, good remote | Recloned working copy or replace .git from fresh clone. |
| Reachable object, no remote | Copy objects from a healthy clone/backup or accept data loss if truly unrecoverable. |
Pitfalls to avoid
- Running prune/gc before backups can permanently delete recoverable objects protected only by reflogs.
- Forcing fetch without moving refs may not re-download interior objects; reclone is more reliable.
- Resetting hard can discard local changes—stash or back up first.
- Corruption can live inside packfiles too; manual surgery on packs is error-prone. Prefer reclone or object copy from a good source.
Performance notes
- git fsck --full is I/O heavy. To triage quickly, start with git fsck --no-dangling.
- Recloning is often faster than chasing multiple corrupt objects in large repos.
- After recovery, run a maintenance pass to optimize future operations:
git gc --prune=now --aggressive
# or, in large repos with CI-friendly bitmaps:
git repack -Ad -l --write-bitmap-index
- On CI, prefer clean clones or reliable repository caches; avoid network filesystems for .git.
- Exclude .git/objects from antivirus scanning and ensure stable storage to reduce risk.
Prevention checklist (DevOps angle)
- Enable object verification on transfer:
git config --global fetch.fsckObjects true
git config --global receive.fsckObjects true
- Monitor disk health; avoid unreliable network mounts for repositories.
- Use UPS on build agents to prevent hard power loss.
- Keep multiple clones or backups for critical repos.
Tiny FAQ
- What is a “loose object”? A single-file object under .git/objects/xx/sha. Packed objects live in .pack files.
- Will git gc fix corruption? It removes unreachable garbage but won’t reconstruct reachable corrupted objects.
- Can git fetch re-download corrupted objects? Not reliably unless refs force the server to resend history. Recloning is the dependable approach.
- Why did this happen? Common causes: disk/FS faults, abrupt termination, antivirus, or corrupted caches in CI.
Summary
- Prefer reclone or .git replacement from a fresh clone when a reachable object is corrupt.
- If objects are only dangling, prune them.
- When remotes are unavailable, copy objects from another healthy clone or backup.
- Always back up first, verify with git fsck, and adopt preventive settings in your DevOps workflows.