You accidentally deleted a branch, ran git reset --hard, or a rebase went wrong. Your commits seem gone. Git reflog tracks every HEAD movement and lets you recover what you thought was lost.
The Scenario
Common ways to lose commits:
```bash # Accidentally reset too far git reset --hard HEAD~3 # Oops, you needed those commits!
# Deleted wrong branch git branch -D important-feature
# Rebase went wrong git rebase origin/main # Conflicts were too complex, aborted, but commits disappeared
# Force pushed wrong branch git push --force origin main # Overwrote remote commits ```
The Error
After losing commits:
git log --oneline -5Shows fewer commits than expected. Your work is missing from history.
Why Recovery Works
Git doesn't immediately delete commits. Unreachable commits stay in the object database for 90 days (default). The reflog records every HEAD position change, creating a history you can navigate back through.
Diagnosis Steps
View the reflog:
``bash
git reflog
Shows all HEAD movements:
abc1234 HEAD@{0}: reset: moving to HEAD~3
def5678 HEAD@{1}: reset: moving to def5678
ghi9012 HEAD@{2}: commit: Add important feature
jkl3456 HEAD@{3}: commit: Fix critical bug
mno7890 HEAD@{4}: checkout: moving from main to feature
pqr1234 HEAD@{5}: commit: Start feature workFind specific operations:
``bash
git reflog show --grep="reset"
git reflog show --grep="commit"
git reflog show --grep="branch"
Check reflog for specific branch:
``bash
git reflog show feature-branch
Solution 1: Reset to Lost Commit
Find the commit you want to recover:
git reflog
# Note HEAD@{N} or commit hashReset to that position:
git reset --hard HEAD@{2}Or use commit hash:
git reset --hard ghi9012Solution 2: Create Branch at Lost Commit
Preserve current state while recovering:
git branch recovery-branch HEAD@{2}Or:
git branch recovery-branch ghi9012Switch to recovered branch:
git checkout recovery-branchSolution 3: Recover Deleted Branch
Find where branch was created or its last position:
git reflog show --grep="branch: Created from"Or find checkout to that branch:
git reflog show --grep="moving to"Recreate the branch:
git branch recovered-feature HEAD@{5}Solution 4: Cherry-Pick Lost Commits
Recover specific commits onto current branch:
# From reflog, note commit hashes
git cherry-pick ghi9012
git cherry-pick jkl3456Each cherry-pick creates a new commit with the same changes.
Solution 5: Find All Dangling Commits
Search for all unreachable objects:
git fsck --lost-foundOutput:
dangling commit ghi9012...
dangling commit jkl3456...
dangling blob abc123...Examine dangling commits:
git show ghi9012
git log ghi9012 --onelineSolution 6: Recover After Bad Rebase
If rebase lost commits:
git reflogFind state before rebase started:
abc1234 HEAD@{0}: rebase (abort): updating HEAD
def5678 HEAD@{1}: rebase (start): checkout origin/main
ghi9012 HEAD@{2}: checkout: moving from main to featureReset to pre-rebase state:
git reset --hard HEAD@{2}Solution 7: Recover After Branch Delete
Find the branch's last commit:
git reflog show deleted-branchOr search for its creation:
git reflog | grep "deleted-branch"Recreate:
git branch deleted-branch HEAD@{3}Solution 8: Partial Recovery with Merge
Recover and merge with current work:
```bash # Create recovery branch git branch recovered HEAD@{2}
# Merge into current branch git merge recovered
# Clean up git branch -d recovered ```
Solution 9: Recover Stashed Work
If stash was accidentally dropped:
git fsck --lost-foundFind dangling commits - stashes are commits.
git show dangling-commit-hashIf it's a stash, recover:
git branch stash-recovery dangling-commit-hashSolution 10: Remote Reflog Recovery
If someone else force-pushed to shared branch:
# Before you fetch/pull
git reflog show origin/mainFind commits before force push:
git branch recovered-remote abc1234Push recovery:
git checkout recovered-remote
git push --force-with-lease origin mainVerification
Confirm recovery:
``bash
git log --oneline -10
Your commits should appear.
Check branch exists:
``bash
git branch -a
Verify file content:
``bash
git show HEAD:path/to/file.txt
Test functionality:
``bash
npm test
Prevention Strategies
Create backup branch before risky operations:
``bash
git branch backup-point
git reset --hard HEAD~3
# If wrong, recover from backup-point
Tag important commits:
``bash
git tag milestone-1
Tags are never lost in reflog.
Enable longer reflog retention:
``bash
git config --global gc.reflogExpire 365.days
git config --global gc.reflogExpireUnreachable 30.days
Prevent accidental garbage collection:
``bash
git config --global gc.auto 0
Run GC manually when needed.
Reflog Timeline
Default retention: - Reachable reflog entries: 90 days - Unreachable reflog entries: 30 days
After expiration, commits are truly deleted by git gc.
Quick Reference
| Scenario | Command |
|---|---|
| View reflog | git reflog |
| Reset to position | git reset --hard HEAD@{N} |
| Create branch at position | git branch name HEAD@{N} |
| Find dangling commits | git fsck --lost-found |
| Cherry-pick lost commit | git cherry-pick abc123 |
| Show commit details | git show abc123 |