Accidentally did ‘git reset –hard’ and lost hours of work? Your commits aren’t deleted – they’re just orphaned. Here’s how to find them.
The Magic Command – Reflog:
git reflog
This shows every HEAD movement in your repository, even deleted commits. Output looks like:
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
e4f5g6h HEAD@{1}: commit: Added user authentication ← Your "lost" commit!
i7j8k9l HEAD@{2}: commit: Updated database schema
Recover the Commit:
# Find your commit hash from reflog
git reflog
# Reset to that commit
git reset --hard e4f5g6h
# Or create a new branch from it (safer)
git checkout -b recovery-branch e4f5g6h
Why This Works:
Git never truly deletes commits immediately. When you reset or delete a branch, Git removes the reference (pointer) but keeps the commit object. These orphaned commits exist for 30-90 days (configurable) before garbage collection removes them.
Advanced – Find Specific Lost Content:
# Search reflog for commits matching a pattern
git reflog --grep='authentication'
# Show all dangling commits (no branch points to them)
git fsck --lost-found
# View content of a dangling commit
git show COMMIT_HASH
Real Disaster Recovery Example:
# Scenario: Deleted feature branch by mistake
git branch -D feature-login
# ERROR: deleted branch 'feature-login'
# Solution 1: Find in reflog
git reflog | grep 'feature-login'
# Output: x1y2z3a HEAD@{5}: commit: Feature login complete
# Recreate branch
git checkout -b feature-login x1y2z3a
# Solution 2: Check recent commits
git fsck --no-reflogs
# Shows all unreachable commits
# Browse each one until you find your work
git log COMMIT_HASH --oneline
Prevent This Entirely – Git Aliases:
# Add safe reset aliases to ~/.gitconfig
[alias]
# Soft reset (keeps changes in staging)
undo = reset --soft HEAD~1
# Show what would be deleted before hard reset
check-reset = !git diff HEAD~1 HEAD
# Safe hard reset with automatic backup
safe-reset = !sh -c 'git branch backup-$(date +%Y%m%d-%H%M%S) && git reset --hard $1' -
# Usage
git safe-reset HEAD~3 # Creates backup branch automatically
Understanding Git’s 30-Day Safety Net:
# Check garbage collection settings
git config gc.reflogExpire
# Default: 90 days for reachable commits
# Default: 30 days for unreachable commits
# Extend safety net to 180 days
git config gc.reflogExpire 180.days.ago
git config gc.reflogExpireUnreachable 180.days.ago
Pro Tip – Periodic Backups:
# Create backup tags for important commits
git tag -a backup-before-refactor -m "Safety checkpoint"
# List all backup tags
git tag -l "backup-*"
# Restore from backup tag
git checkout backup-before-refactor
git checkout -b recovery-branch
Tags are permanent references. Even if you delete all branches, tagged commits never become unreachable.
