Topic 5.3
Reflog: Your Undo Button for (Almost) Everything
In one line
git reflog is a private, local log of every place HEAD has pointed to recently — including commits that a bad reset or rebase seemingly erased — making most 'I think I just destroyed my work' moments completely recoverable.
Think of it like this
A browser's history tracking every page you've visited, even ones you didn't bookmark — letting you find your way back to something you didn't think to save deliberately. The reflog is exactly this for Git: a record of everywhere HEAD has been recently, regardless of whether any branch currently points there.
Key ideas
- 01
Every time HEAD moves — a commit, a checkout, a reset, a rebase, a merge — Git silently records that move in the REFLOG.
git reflogshows this history, most recent first, each entry with a short description of what operation caused that move (commit,checkout,reset: moving to...,rebase (start), and so on). - 02
This means a commit that seems to have DISAPPEARED after a bad
git reset --hard(Topic 1.3) or a rebase gone wrong usually ISN'T actually gone — it still exists as a real object in Git's storage, simply no longer pointed to by any branch. The reflog remembers exactly where HEAD was pointing right before the operation that seemed to lose it. - 03
Recovery is genuinely simple once you find the right entry:
git reflogto find the SHA HEAD pointed to before the mistake, thengit reset --hard <that-sha>(moving your branch back to it) orgit checkout <that-sha>to inspect it first, orgit branch recovery-branch <that-sha>to save it under a new branch name without touching your current branch at all. - 04
The reflog is LOCAL and PRIVATE to your own machine — it's not pushed, not shared, and not part of the repository's real, permanent history that anyone else sees. It exists purely as your own personal safety net, and it eventually expires (commits unreachable by any branch AND absent from the reflog for long enough become eligible for actual garbage collection, though the default expiry window is generously long, typically 90 days).
- 05
The genuinely important habit this topic teaches: when something in Git seems to have gone catastrophically wrong, the very first move should be
git reflog, not panic — in the overwhelming majority of real 'I lost my work' situations, the commit is still sitting right there, onegit reset --hardaway from being fully restored.
Code & diagrams
The commit still exists — only the branch pointer moved. The reflog remembers where it used to be.
A real 'oh no' scenario, fully recovered.
cd ~/scratch/my-first-repo
# Make a genuinely important commit
echo "important work" >> important.txt
git add important.txt
git commit -m "Important feature work"
git log --oneline -1
# note this SHA — e.g. d4e5f6a
# Disaster: reset one commit too far, "losing" it
git reset --hard HEAD~1
git log --oneline -1
# the important commit is gone from the branch's visible history
# DON'T PANIC — check the reflog first
git reflog
# HEAD@{0} reset: moving to HEAD~1
# HEAD@{1} commit: Important feature work <- there it is
# HEAD@{2} ...
# Recover it directly
git reset --hard HEAD@{1}
# or, using the actual SHA it shows:
# git reset --hard d4e5f6a
git log --oneline -1
# "Important feature work" is back, exactly as it was
# Safer alternative if you're not 100% sure yet: recover to a NEW branch first
git branch recovered-work HEAD@{1}
# inspect it safely before deciding whether to reset your real branch to itExplain it without notes
Why is a commit usually still recoverable after a bad git reset --hard, even though it no longer appears in git log?
Why doesn't the reflog help recover uncommitted changes that were lost in a git reset --hard?
Practice
Make a commit, then deliberately 'lose' it with git reset --hard HEAD~1, and recover it using git reflog and git reset --hard on the recovered SHA.
Delete a branch with unmerged work using git branch -D, then use git reflog to find its tip commit's SHA and restore it under a new branch name.
Trade-offs
- ↔
The reflog is a genuinely powerful safety net, but it's not infinite or permanent — it's local-only (never helps if the mistake happened on a machine you don't have access to anymore) and eventually expires unreachable commits during garbage collection (default ~90 days for unreachable ones) — it's real insurance for recent mistakes, not a permanent archive, which is exactly why genuinely important work still belongs pushed to a remote, not just trusted to local reflog recovery indefinitely.
Done when you can
I know git reflog exists and shows a local history of everywhere HEAD has pointed.
I can recover a commit that seems lost after a bad reset or rebase using the reflog.
I understand the reflog only helps with committed work, and that it isn't permanent or shared.