Recovery Techniques
Quick Summary
Git is designed so that data loss requires deliberate effort. Even after reset --hard, deleted branches, or bad rebases, your data usually still exists in the reflog or object database. This page covers systematic recovery techniques for worst-case scenarios.
git reflog — Your Safety Net
The reflog records every position HEAD has been in. Even after destructive operations, you can find and restore previous states.
git reflog
a1b2c3d HEAD@{0}: reset: moving to HEAD~3 ← oops!
d4e5f6a HEAD@{1}: commit: feat: add dashboard
c3d4e5f HEAD@{2}: commit: feat: add sidebar
b2c3d4e HEAD@{3}: commit: feat: add layout
e5f6a7b HEAD@{4}: checkout: moving from feature to main
Recover from the Reflog
# Go back to a specific reflog entry
git reset --hard HEAD@{1}
# Or create a branch from a reflog entry
git branch recovery HEAD@{1}
Common Recovery Scenarios
Recover Deleted Branch
# Find the last commit of the deleted branch
git reflog | grep "checkout: moving from deleted-branch"
# Recreate the branch at that commit
git branch recovered-branch <commit-hash>
Recover After git reset --hard
# Find the commit you were at before the reset
git reflog
# Reset back to it
git reset --hard HEAD@{1}
Recover Lost Commits After Rebase
# Find pre-rebase state in reflog
git reflog | head -20
# Restored the original branch tip
git reset --hard HEAD@{N} # where N is the pre-rebase entry
Recover Deleted File
# Find the last commit that had the file
git log --all --full-history -- path/to/deleted-file.js
# Restore it from that commit
git checkout <commit-hash> -- path/to/deleted-file.js
Find Orphaned Commits
# Show all commits not reachable from any branch or tag
git fsck --lost-found
# Inspect dangling commits
git show <dangling-commit-hash>
# Recover by creating a branch
git branch rescue <dangling-commit-hash>
Fixing Repository Corruption
# Check repository integrity
git fsck --full
# If objects are corrupted, try:
git gc --prune=now
git fsck --full
# Clone a fresh copy from remote (last resort)
cd ..
git clone git@github.com:donnyaw/project.git project-fresh
Prevention: Reflog Expiry
By default, reflog entries expire after 90 days (reachable) or 30 days (unreachable). To extend:
# Keep reflog entries for 1 year
git config --global gc.reflogExpire 365.days
git config --global gc.reflogExpireUnreachable 365.days
Recovery Decision Table
| What Happened | Recovery Method |
|---|---|
| Deleted a branch | git reflog → git branch <name> <hash> |
git reset --hard | git reflog → git reset --hard HEAD@{N} |
| Lost commits after rebase | git reflog → git reset --hard HEAD@{N} |
| Deleted a file | git log --all -- <file> → git checkout <hash> -- <file> |
| Orphaned commits | git fsck --lost-found → git branch rescue <hash> |
| Repo corruption | git fsck --full → git gc → re-clone if needed |
Best Practices
- Know
git reflogexists — it's your first recovery tool - Push frequently — remote serves as your backup
- Don't run
git gcafter mistakes — garbage collection may remove recoverable objects - Extend reflog expiry for critical repositories
- Make backups before destructive operations —
git branch backup-before-rebase
What's Next
- Cheatsheet — Basic Commands — Quick reference card
- AI Collaboration — Use AI assistants for Git workflows