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:

bash
git log --oneline -5

Shows 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:

bash
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 work

Find 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:

bash
git reflog
# Note HEAD@{N} or commit hash

Reset to that position:

bash
git reset --hard HEAD@{2}

Or use commit hash:

bash
git reset --hard ghi9012

Solution 2: Create Branch at Lost Commit

Preserve current state while recovering:

bash
git branch recovery-branch HEAD@{2}

Or:

bash
git branch recovery-branch ghi9012

Switch to recovered branch:

bash
git checkout recovery-branch

Solution 3: Recover Deleted Branch

Find where branch was created or its last position:

bash
git reflog show --grep="branch: Created from"

Or find checkout to that branch:

bash
git reflog show --grep="moving to"

Recreate the branch:

bash
git branch recovered-feature HEAD@{5}

Solution 4: Cherry-Pick Lost Commits

Recover specific commits onto current branch:

bash
# From reflog, note commit hashes
git cherry-pick ghi9012
git cherry-pick jkl3456

Each cherry-pick creates a new commit with the same changes.

Solution 5: Find All Dangling Commits

Search for all unreachable objects:

bash
git fsck --lost-found

Output:

bash
dangling commit ghi9012...
dangling commit jkl3456...
dangling blob abc123...

Examine dangling commits:

bash
git show ghi9012
git log ghi9012 --oneline

Solution 6: Recover After Bad Rebase

If rebase lost commits:

bash
git reflog

Find state before rebase started:

bash
abc1234 HEAD@{0}: rebase (abort): updating HEAD
def5678 HEAD@{1}: rebase (start): checkout origin/main
ghi9012 HEAD@{2}: checkout: moving from main to feature

Reset to pre-rebase state:

bash
git reset --hard HEAD@{2}

Solution 7: Recover After Branch Delete

Find the branch's last commit:

bash
git reflog show deleted-branch

Or search for its creation:

bash
git reflog | grep "deleted-branch"

Recreate:

bash
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:

bash
git fsck --lost-found

Find dangling commits - stashes are commits.

bash
git show dangling-commit-hash

If it's a stash, recover:

bash
git branch stash-recovery dangling-commit-hash

Solution 10: Remote Reflog Recovery

If someone else force-pushed to shared branch:

bash
# Before you fetch/pull
git reflog show origin/main

Find commits before force push:

bash
git branch recovered-remote abc1234

Push recovery:

bash
git checkout recovered-remote
git push --force-with-lease origin main

Verification

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

ScenarioCommand
View refloggit reflog
Reset to positiongit reset --hard HEAD@{N}
Create branch at positiongit branch name HEAD@{N}
Find dangling commitsgit fsck --lost-found
Cherry-pick lost commitgit cherry-pick abc123
Show commit detailsgit show abc123