The reflog: your safety net
Git records every movement of HEAD in the reflog - resets, checkouts, rebases, amends, merges. Even commits no branch points to are kept reachable for ~90 days (configurable via gc.reflogExpire). When you "lose" a commit, it is almost always still in the reflog.
Inspecting the reflog
git reflog # HEAD's reflog
git reflog show feature/login # a specific branch's reflog
git log -g # reflog as a log
Each entry shows a SHA, a relative reference (HEAD@{3}), and the action that produced it.
Recovering a deleted branch
git reflog | grep checkout # find when you last had it
git checkout -b recovered <sha>
Even after git branch -D, the commit is reachable for the reflog expiry window.
Undoing a bad reset
# You did:
git reset --hard HEAD~5
# Recover:
git reflog
# Find HEAD@{1} - the SHA before the reset
git reset --hard HEAD@{1}
Undoing a bad rebase
git reflog
# Look for "rebase (start)" entries; the commit before is your pre-rebase tip.
git reset --hard ORIG_HEAD
# Or, more explicitly:
git reset --hard HEAD@{N}
Git also keeps the pre-operation SHA in ORIG_HEAD for resets, merges, and rebases.
Recovering an amended commit
git commit --amend # uh, that was wrong
git reflog
# HEAD@{1} is the pre-amend commit
git reset --hard HEAD@{1}
Finding orphaned commits
If the reflog has expired, dangling commits can still be found until garbage collection:
git fsck --lost-found
# Or:
git fsck --no-reflog | grep "dangling commit"
Inspect with git show <sha>; rescue with git branch rescue <sha>.
Reflog versus stash
Stashes also live in a reflog (git stash list shows it). A dropped stash can be recovered the same way:
git fsck --no-reflog | awk '/dangling commit/ {print $3}'
git stash apply <sha>
Configuring reflog expiry
git config gc.reflogExpire 180.days
git config gc.reflogExpireUnreachable 90.days
Default is 90 and 30 days respectively. Increase for paranoia, decrease to free disk on very large repos.
The cardinal rule
Before you panic and ask the team for help, run git reflog. In nine cases out of ten the commit is right there, two HEAD positions back, waiting to be reset to. Reflog has saved more careers than any other Git feature.