Skip to main content

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 HappenedRecovery Method
Deleted a branchgit refloggit branch <name> <hash>
git reset --hardgit refloggit reset --hard HEAD@{N}
Lost commits after rebasegit refloggit reset --hard HEAD@{N}
Deleted a filegit log --all -- <file>git checkout <hash> -- <file>
Orphaned commitsgit fsck --lost-foundgit branch rescue <hash>
Repo corruptiongit fsck --fullgit gc → re-clone if needed

Best Practices

  • Know git reflog exists — it's your first recovery tool
  • Push frequently — remote serves as your backup
  • Don't run git gc after mistakes — garbage collection may remove recoverable objects
  • Extend reflog expiry for critical repositories
  • Make backups before destructive operationsgit branch backup-before-rebase

What's Next

  1. Cheatsheet — Basic Commands — Quick reference card
  2. AI Collaboration — Use AI assistants for Git workflows