You force-pushed over the wrong branch, someone ran git reset --hard on shared history, or your repo suddenly throws “fatal: not a git repository” errors. Panic makes it worse. Git rarely deletes data outright — it mostly just loses track of it — so in most cases your commits are still sitting on disk waiting to be found.
First: stop and don’t run anything destructive
Before typing another command, avoid git gc, git clean -f, or cloning over the same folder. Garbage collection is the one thing that can actually delete unreferenced commits, and it runs automatically sometimes. Copy the entire .git folder somewhere safe first:
cp -r .git .git.backup-$(date +%s)
Symptom 1: I deleted a branch or lost commits after a reset
The reflog tracks every place HEAD has pointed, including commits that no branch references anymore.
git reflog
# find the commit hash before the reset/checkout
git reset --hard HEAD@{2}
# or, safer, create a new branch from that point
git branch recovered-branch HEAD@{2}
Reflog entries expire (default 90 days for reachable commits, 30 for unreachable), so this works best soon after the mistake.
Symptom 2: a commit was overwritten or amended by mistake
If the reflog doesn’t show what you need (for example, someone else force-pushed), search all dangling objects directly:
git fsck --lost-found
git fsck --unreachable --no-reflogs
This lists dangling commit and blob SHAs. Inspect any promising commit with:
git show <sha>
git log --stat <sha>
If it’s the commit you lost, cherry-pick it back or create a branch pointing at it: git branch recovered <sha>.
Symptom 3: a specific file’s content is gone but you know the blob exists
git cat-file -p <blob-sha> > recovered-file.txt
# find candidate blobs if you don't have the sha
git rev-list --objects --all | grep "path/to/file"
Symptom 4: the repo itself looks broken (corrupted objects, index errors)
git fsck --full
git count-objects -v
If fsck reports corrupt objects and you have any other clone or a remote (GitHub, GitLab, a teammate’s machine), the fastest fix is usually to re-fetch missing objects rather than repair locally:
git remote add temp-recovery /path/to/other/clone/.git
git fetch temp-recovery
If no clean copy exists anywhere, try rebuilding the index and re-cloning objects one by one is a last resort — at that point, prioritize copying out working files you can still read from disk before touching git internals further.
A decision tree you can actually use
- Lost branch/commit locally, still on your machine: check
git reflogfirst. - Reflog doesn’t have it (old, or reflog itself was cleared): run
git fsck --unreachable. - Need one file’s old content: use
git cat-fileon the blob SHA. - Repo itself is corrupted (bad objects, index errors): check for a clean remote or teammate copy before attempting local repair.
Understanding what these commands actually do — instead of copy-pasting them under panic — is a lot easier if you’re comfortable with git’s model in the first place. See How to learn Git without hating it for that foundation, and Git add, commit, and push in one command if you want to speed up your normal workflow once the fire is out.
Quick FAQ
Will git gc delete my lost commits?
It can, once they’re unreachable and past the reflog expiry window. Avoid running it during recovery.
Can I recover commits I never committed locally (only staged)?
Staged content is stored as a blob object as soon as you run git add, so git fsck --unreachable can often still find it even without a commit.
What’s the single best habit to avoid this?
Push to a remote often. A remote is the simplest, most reliable backup you already have.
Leave a Reply