git reflog
Advanced Git CLI Safe
Summary: git reflog lists every position HEAD has held in this clone, newest first, with what moved it. It is how you find a commit that git log can no longer see.
Safe — it only reads. Nothing in this command changes anything.
What it does
Prints the reference log: a local record Git writes every time HEAD or a branch moves, whether by commit, checkout, merge, rebase, reset or pull. Each line gives the hash the reference pointed at afterwards, a position such as HEAD@{2}, and the action.
Why it exists
Branches are pointers, and pointers move. Without a record of where they have been, a git reset --hard would leave a commit with no way to name it. The reflog is that record, and it is the reason a committed change is almost never lost.
When to use it
- After a reset, rebase or amend removed something you wanted.
- To find a deleted branch's last commit.
- To answer "where was
mainyesterday?". - Before any risky operation, to note the current position.
When not to use it
- To find work you never committed. The reflog holds commits; uncommitted edits were never recorded.
- To find what a colleague did. It is local to your clone and is never pushed or fetched.
Syntax
| Form | Effect |
|---|---|
git reflog |
The log for HEAD |
git reflog show <branch> |
The log for that branch, as <branch>@{n} |
git reflog --date=relative |
Show "2 hours ago" instead of positions |
git reflog -20 |
Limit the number of entries |
main@{yesterday} |
Valid anywhere a commit is expected |
git reflog expire --expire=now --all |
Delete entries; almost never what you want |
Examples
Find a commit removed by a reset:
$ git reflogb81702c HEAD@{0}: reset: moving to HEAD~1
d3b92ec HEAD@{1}: checkout: moving from docs/12-windows-install-steps to main
95a0014 HEAD@{2}: commit: docs: add Windows steps to installation guide (#12)
d3b92ec HEAD@{3}: checkout: moving from main to docs/12-windows-install-steps
d3b92ec HEAD@{4}: commit: chore: add CI configuration and contributing guideHEAD@{2} is the commit that git log no longer shows. Bring it back:
$ git reset --hard HEAD@{1}HEAD is now at d3b92ec chore: add CI configuration and contributing guideOr give the lost commit a branch instead, which is safer:
$ git branch rescue/windows-steps 95a0014One branch's history:
$ git reflog show maind3b92ec main@{0}: reset: moving to ORIG_HEAD
28593d2 main@{1}: reset: moving to HEAD~2
d3b92ec main@{2}: reset: moving to HEAD@{1}
b81702c main@{3}: reset: moving to HEAD~1
d3b92ec main@{4}: commit: chore: add CI configuration and contributing guideExpected result
A list, newest first. Nothing changes; the command is a lookup.
Common mistakes
- Expecting it on the server. It is local by definition.
- Counting
HEAD@{n}instead of reading the messages. The message names the action, which is a far more reliable way to identify the entry you want. - Waiting. Entries expire after about ninety days, and unreachable commits are collected after that.
- Running
git gc --prune=nowwhile recovering, which removes the objects you are looking for. - Assuming it covers uncommitted work.
How to undo or recover
Nothing to undo. If a recovery attempt went wrong, the attempt is itself in the reflog: run it again and pick an earlier entry.
In VS Code
No reflog view. Use the built-in terminal.
In IntelliJ IDEA
No direct reflog view either, but Git → Recent Branches covers the common case of returning to a branch, and Local History covers work Git never saw, which the reflog cannot help with.
Related commands
git reset to move a branch to an entry you found · git branch to name a rescued commit · git log for reachable history · git show to inspect a candidate hash.
Lessons that use this command
The safety net and the reflog · Recover files, branches, commits · Force push.