git reflog
`git reflog` records every change to HEAD on every branch in your local clone. It is the safety net for "I deleted that commit", "I force-pushed over it", "rebase ate my work". Reflog entries last ~90 days by default and are LOCAL — so they survive force-pushes but not a fresh clone. Learn it before you need it.
Find, recover, and curate your local reflog
EXAMPLE
# 1) See where HEAD has been
git reflog # newest at the top
git reflog --date=iso # include real timestamps
git reflog show main # per-branch reflog (a different log)
# 2) Recover a 'lost' commit after a reset, rebase, or branch delete
git reflog | head -20 # find the lost SHA
git reset --hard HEAD@{4} # or use the raw SHA
# Note HEAD@{N} = where HEAD was N moves ago
# 3) Reattach a detached HEAD's work as a new branch
git checkout -b rescued 9fceb02
# 4) Undo a bad rebase or merge
git reflog # find the commit before the bad rebase
git reset --hard HEAD@{12} # reset to that snapshot
# Or, if it's clearly named:
git reset --hard ORIG_HEAD # set automatically before destructive ops
# 5) After a 'whoops, I deleted that branch'
git reflog | grep -i 'feature-x'
# Recover the tip and re-create the branch
git checkout -b feature-x abc1234
# 6) Inspect a specific reflog entry
git show HEAD@{7} # the commit HEAD pointed at 7 moves back
git diff HEAD@{7} HEAD # what changed since
# 7) When the reflog is NOT enough
# - You never had the commit locally (only on the remote, and someone deleted the ref)
# - Your reflog has been pruned (gc.reflogExpire defaults to 90 days)
# - You re-cloned, wiping the local reflog
# In those cases, look on the remote:
git ls-remote --refs origin # surviving refs only
# Or open the host UI; GitHub keeps deleted commits reachable for ~30 days.
# 8) Curate / expire — usually unnecessary
git reflog expire --expire=30.days.ago --all
git reflog expire --expire-unreachable=7.days.ago --all
git gc --prune=now # actually remove unreachable objects
# 9) Two reflogs to know about
# HEAD reflog: git reflog (where HEAD has been)
# Branch reflog: git reflog show <ref> (where this ref has been)
# Stash reflog: git reflog show stash (your stash history)
# 10) Make recovery a reflex
# Alias for the common 'find a lost commit, look at it, decide what to do':
git config --global alias.last 'reflog -n 20 --date=iso'
git config --global alias.unduck 'reset --hard HEAD@{1}' # undo the last destructive op
# 11) Confidence-builder
# Before any scary command (rebase -i, reset --hard, filter-branch), run:
git tag _SAFETY HEAD # creates a movable bookmark
# If anything goes wrong:
git reset --hard _SAFETY
git tag -d _SAFETY
Why it matters
`git reflog` is the offline undo button most teams discover after their first force-push regret. Make it part of the muscle memory: before any destructive command, glance at `git reflog | head` so you know where HEAD is — then if the next step is wrong, `git reset --hard HEAD@{1}` rolls back to exactly where you started.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
git reflog # ALL ref movements — recover "lost" commits
git reset --hard HEAD@{2}
Try it Yourself »
Discussion
Loading…