Git rarely loses data outright, but a bad recovery attempt can. This skill's core principle: snapshot before touching anything, and prefer the least destructive fix that resolves the actual problem.
First move, always
Before running anything else, capture the current state so it can be recovered even if the next steps go wrong:
git status
git branch -a
git log --oneline -5
git switch -c rescue/<timestamp>
Creating a rescue branch from wherever HEAD currently points means nothing is lost even if the "real" fix goes sideways — you can always get back to this exact commit.
Diagnosing common states
- Detached HEAD:
git statuswill say so directly. Checkgit log --oneline -5to see if there's meaningful work here before deciding whether to create a branch from it or discard it. - Stuck index/worktree lock (
.git/index.lockor a worktree "locked" error): check whether another process is actually still running before removing the lock file — a lock removed while git is genuinely mid- operation can corrupt the index. - Orphaned/dangling commits:
git fsck --lost-foundandgit reflogbefore assuming work is gone — the reflog holds recent HEAD positions even after a reset or rebase that "lost" a branch pointer.
Recovery order, least to most destructive
- Reconnect to the intended branch (
git switch <branch>) if the work is simply detached, not actually damaged. - Cherry-pick or merge the rescue branch's commits onto the intended branch if history diverged.
- Only reach for
reset --hard,clean -f, or force-push after confirming (via the rescue branch made in step one) that nothing needed is only reachable through the state being discarded.
The rule
Treat .git/ as production data. Never run a destructive git command
without first confirming, concretely, what would be lost if the assumption
behind it is wrong.