Recovering Lost Work with reflog
A bad git reset or a force-deleted branch feels like a disaster — until you learn the reflog. By the end of this lesson you'll be able to look up exactly where your code was before any mistake and bring it straight back.
Learn Recovering Lost Work with reflog in our free Git course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Git course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn
1️⃣ What the reflog Records
The reflog (reference log) is a local diary of every position HEAD has held. Every commit, reset, checkout, merge, and rebase adds an entry. Crucially, it remembers commits even after no branch points at them — which is what makes it a lifesaver. Each line reads <hash> HEAD@ { n } : <move> , with HEAD@ { 0 } being right now.
2️⃣ The Disaster: a Bad Hard Reset
A git reset --hard HEAD~2 moves your branch back two commits and discards the working changes. It looks like the newer commits are gone — git log can't see them. But they're only unreferenced , not deleted, and the reflog logged the reset itself plus the tip you left behind.
3️⃣ The Rescue
Recovery is just pointing your branch back at the lost commit. Use the hash you read from the reflog, or the HEAD@ { n } reference — they resolve to the same commit. git reset --hard moves the branch; git branch recovered <hash> rescues the work onto a new branch without disturbing where you are.
Your turn. Recover after a bad reset by reading the reflog and pointing the branch back. Fill in the two blanks.
4️⃣ Recovering a Deleted Branch
Even a force-delete is recoverable. git branch -D feature-login prints (was 9a8b7c6) — that's the tip you discarded. Rebuild the branch with git branch feature-login 9a8b7c6 . If you've already lost the hash, the reflog still has it.
Common Errors (and the fix)
- "fatal: ambiguous argument 'HEAD@ { 1 } '": your shell may be eating the braces — wrap the reference in quotes: git reset --hard "HEAD@ { 1 } " .
- Confusing HEAD@ { 1 } with HEAD~1 : the first means "one reflog move ago"; the second means "one commit back in history". They are usually different commits.
- Reflog looks empty in a fresh clone: that's expected — the reflog is local and isn't transferred by clone. It starts recording from your first action in that copy.
- "unknown revision" when recovering an old commit: the entry may have been pruned by git gc . Recover promptly; entries expire (about 30–90 days by default).
Pro Tips
- 💡 Before any risky reset or rebase: note the current hash (or make a backup branch) so recovery is trivial.
- 💡 Per-branch reflog: git reflog show main shows just where main has moved.
- 💡 See details: git log -g --oneline walks the reflog with commit info attached.
- 💡 Truly orphaned objects: git fsck --lost-found can surface dangling commits the reflog missed.
📋 Quick Reference
Command
Purpose
git reflog
Show HEAD's full movement history
git reflog show main
Reflog for one branch
git reset --hard HEAD@ { 1 }
Move branch to a reflog position
git branch name <hash>
Rebuild a deleted branch at a hash
git log -g --oneline
Walk the reflog with commit details
git fsck --lost-found
Find dangling commits
Frequently Asked Questions
Mini-Challenge: Break It, Then Save It
No commands given this time — just the plan. Deliberately lose some commits and bring them all back using only the reflog.
🎉 Lesson Complete!
- ✅ The reflog is a local diary of every place HEAD has pointed
- ✅ A bad reset --hard only unreferences commits — the reflog still has them
- ✅ Recover with git reset --hard HEAD@ { n } or the commit hash
- ✅ Rebuild a force-deleted branch with git branch name <hash>
- ✅ The reflog is local-only and entries expire — recover promptly
- ✅ Next lesson: find out exactly who changed each line with git blame
Practice quiz
What does git reflog record?
- Every commit anyone ever pushed
- The remote branch history
- A local log of where HEAD (and branch tips) have pointed over time
- Only merge commits
Answer: A local log of where HEAD (and branch tips) have pointed over time. The reflog is a local diary of every position HEAD has held — commits, resets, checkouts, merges, rebases.
After 'git reset --hard HEAD~2', how do you find the lost commits?
- git reflog — the old tip still appears as HEAD@{1}
- They are gone forever
- git fsck only
- Re-clone the repo
Answer: git reflog — the old tip still appears as HEAD@{1}. The reset is itself logged, and the previous HEAD position remains in the reflog as HEAD@{1}.
What does the notation HEAD@{1} mean?
- The commit one before the current branch tip
- The first commit in the repo
- The remote HEAD
- Where HEAD pointed one reflog move ago
Answer: Where HEAD pointed one reflog move ago. HEAD@{n} is a reflog reference: where HEAD was n moves ago, not n commits back in history.
How do you restore your branch to a lost commit shown in the reflog?
- git reflog restore
- git reset --hard <hash> (or HEAD@{n})
- git pull
- git commit --amend
Answer: git reset --hard <hash> (or HEAD@{n}). Once you read the hash from the reflog, git reset --hard <hash> moves the branch back to it.
Is the reflog shared with collaborators when you push?
- No, the reflog is purely local to your clone
- Yes, it is pushed automatically
- Only with --all
- Only on the default branch
Answer: No, the reflog is purely local to your clone. The reflog lives in .git/logs and is never transferred by push, fetch, or clone.
You deleted a branch with -D before merging. Can you get it back?
- No, force-delete is permanent
- Only if you had pushed it
- Yes — the reflog shows the deleted tip's hash so you can recreate the branch
- Only with git stash
Answer: Yes — the reflog shows the deleted tip's hash so you can recreate the branch. git branch -D prints '(was <hash>)' and the reflog keeps that hash, so git branch name <hash> rebuilds it.
How long do reflog entries typically last by default?
- Forever
- About 90 days for reachable, 30 days for unreachable entries before gc prunes them
- 1 day
- Until the next commit
Answer: About 90 days for reachable, 30 days for unreachable entries before gc prunes them. gc.reflogExpire defaults to 90 days (30 for unreachable), so recover lost work promptly.
Which command recreates a deleted branch at a recovered hash?
- git reflog feature
- git checkout --orphan
- git restore feature
- git branch feature <hash>
Answer: git branch feature <hash>. git branch <name> <hash> creates a new branch pointing at the recovered commit.
What is the difference between git log and git reflog?
- Nothing
- git log walks commit ancestry; git reflog lists HEAD's movement history, including commits no longer in any branch
- reflog is remote-only
- log is local-only
Answer: git log walks commit ancestry; git reflog lists HEAD's movement history, including commits no longer in any branch. git log follows parents of reachable commits; reflog can reach 'dangling' commits a reset orphaned.
Which flag shows reflog-style entries through git log instead?
- git log --reflog
- git log --orphans
- git log -g (or --walk-reflogs)
- git log --recover
Answer: git log -g (or --walk-reflogs). git log -g walks the reflog, combining commit details with reflog ordering.
Continue this course
- Previous: Cherry-Picking Commits
- Next: Finding Who Changed What with git blame