Sooner or later, everyone using Git has a moment of panic. You ran git reset --hard and your last three commits disappeared. You deleted a branch with -D before it was merged. A rebase went wrong and your history looks nothing like it did. It feels as though work is gone forever.
Usually, it isn't. Git quietly keeps a diary called the reflog (reference log) that records every time HEAD or a branch tip moves: every commit, checkout, reset, merge, rebase and amend. Commits that no branch points to any more are still stored in the repository for weeks, and the reflog tells you exactly where to find them.
In this lesson you'll read the reflog, undo a hard reset, bring back a deleted branch, rescue work after a bad rebase, and learn the limits of what Git can recover, so you know when to stop worrying and when to be careful.
Reading the reflog
git reflogEach line shows where HEAD pointed after an action, newest first:
1e2f3a4 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~3
9c8b7a6 HEAD@{1}: commit: Add checkout page
5d4c3b2 HEAD@{2}: commit: Add basket pageHEAD@{0}is where HEAD is now,HEAD@{1}where it was one move ago, and so on.- The description says what moved it: commit, checkout, reset, merge, rebase or pull.
- The hash on the left is the commit HEAD pointed to at that moment, and it can be used like any other commit reference.
Undoing a hard reset
git reset --hard moves your branch back and discards changes, but the commits it skipped over still exist. To undo it, find the entry from just before the reset and reset back to it:
git reflog
git reset --hard HEAD@{1}Read the reflog carefully first: the right entry is the one just before the "reset: moving to" line. If you'd rather not move your branch, create a new branch at the lost commit instead: git branch rescued 9c8b7a6.
Restoring a deleted branch
Deleting a branch only removes its label; its commits remain for a while. When you delete with git branch -D, Git even prints the hash: Deleted branch spike (was 0f3e1a9). Recreate the branch from it:
git branch spike 0f3e1a9If you no longer have that message, search the reflog for the last time you were on the branch, for example the commit message or a "checkout: moving from spike" line, and use that hash.
After a bad rebase, and the limits
A rebase records an entry before it starts. If the result is wrong and you've finished the rebase, find the line just before rebase (start) and reset to it, or use ORIG_HEAD, which Git sets to your branch's previous position before risky operations such as rebase, merge and reset: git reset --hard ORIG_HEAD.
The reflog has limits:
- It's local: it records your repository only, and isn't pushed or cloned.
- Entries expire, by default after 90 days, or 30 days for commits not on any branch, and garbage collection then removes the commits.
- Changes that were never committed aren't recorded. Work discarded with
git restoreorgit reset --hardbefore any commit can't be recovered by Git.
Git Reflog Syntax
Recovery commands
git reflog
git reflog show feature
git reset --hard HEAD@{2}
git branch rescued <hash>
git switch -c rescued HEAD@{3}
git reset --hard ORIG_HEADGit Reflog Summary
- The reflog records every move of HEAD and branch tips in your local repository.
HEAD@{n}refers to where HEAD was n moves ago.- Undo a hard reset with
git reset --hard HEAD@{n}or create a branch at the lost commit. - Restore deleted branches with
git branch <name> <hash>;ORIG_HEADpoints to your pre-rebase position. - The reflog is local, expires after weeks, and can't recover changes that were never committed.
Git Reflog Examples
Each example shows the code, the output it produces and what each part does.
Undoing an accidental hard reset
git reset --hard HEAD~2
git log --oneline -1
git reflog -3
git reset --hard HEAD@{1}
git log --oneline -1HEAD is now at 9d41e07 Add contact form
9d41e07 (HEAD -> main) Add contact form
9d41e07 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~2
c3d9e8f HEAD@{1}: commit: Add FAQ section
52ac9e1 HEAD@{2}: commit: Add dark colour scheme
HEAD is now at c3d9e8f Add FAQ section
c3d9e8f (HEAD -> main) Add FAQ sectionLine-by-line explanation
- Line 1Oops: the last two commits vanish from the branch.
- Line 3The reflog still lists them. HEAD@{1} is where main was just before the reset.
- Line 4Reset back to that point, and both commits return.
Bringing back a deleted branch
git branch -D spike
git branch spike 0f3e1a9
git log --oneline spike -1Deleted branch spike (was 0f3e1a9).
0f3e1a9 (spike) Try a new layoutLine-by-line explanation
- Line 1Force-deleting an unmerged branch. Git still prints the hash it pointed to.
- Line 2Recreate the branch at that commit.
- Line 3The branch and its work are back.
Recovering from a bad rebase with ORIG_HEAD
git rebase main
git log --oneline -3
git reset --hard ORIG_HEAD
git log --oneline -3Successfully rebased and updated refs/heads/search-box.
8a3b2f7 (HEAD -> search-box) Style search box
5c1e9d0 Add search box
7e1c0d2 (main) Fix footer link
HEAD is now at 4b9a8c3 Style search box
4b9a8c3 (HEAD -> search-box) Style search box
2d6f1e4 Add search box
9d41e07 Add contact formLine-by-line explanation
- Line 1The rebase finished, but you decide you'd rather have merged.
- Line 3ORIG_HEAD points to where the branch was before the rebase.
- Line 4The original commits, with their original hashes, are back.
Common Git Reflog Mistakes
Panicking and re-cloning
rm -rf my-project
git clone https://github.com/samlee/my-project.git # unpushed commits are gone for goodgit reflog
git reset --hard HEAD@{1}The reflog lives in your local .git folder. Deleting the folder deletes the rescue route.
Resetting to the wrong reflog entry
git reset --hard HEAD@{0} # that's where you already aregit reflog # read first
git reset --hard HEAD@{1} # the entry before the bad actionExpecting Git to recover uncommitted edits
git restore styles.css # uncommitted edits discarded
git reflog # nothing to recovergit stash # or commit, before discarding anythingGit Reflog in Real Projects
The reflog as a safety net
Experienced developers rewrite history confidently, with rebases, amends and resets, partly because they know the reflog has their back. Support channels for Git tools are full of "I lost my commits!" questions that end happily with two commands: git reflog and git reset --hard HEAD@{n}.
Git Reflog FAQ
How long does Git keep reflog entries?
By default, entries for commits still reachable from a branch are kept for 90 days, and entries for commits that are no longer reachable for 30 days. After that, git gc can remove them. The settings are gc.reflogExpire and gc.reflogExpireUnreachable if you need longer.
Is the reflog shared when I push?
No. The reflog is a private record of where your own branches and HEAD have pointed on your machine. It isn't pushed or cloned, so a fresh clone starts with an empty reflog and you can't use someone else's to recover their work.
What is the difference between git log and git reflog?
git log follows parent links from a commit, so it shows the project's history. git reflog shows where HEAD or a branch has pointed over time, including commits that no longer appear in any branch's history. That's why the reflog can find commits that git log can't.
How do I see when each reflog entry happened?
Add a date format: git reflog --date=relative shows entries like HEAD@{2 hours ago}, and --date=iso shows full timestamps. git log -g shows the same reflog walk in the full git log format.
Can I use reflog entries with other Git commands?
Yes. Names such as HEAD@{2} work anywhere Git expects a commit: git show HEAD@{2}, git diff HEAD@{1} or git switch -c rescue HEAD@{3}. You can also use times, as in main@{yesterday}, for where main pointed a day ago.
Git Reflog Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the command that shows where HEAD has been.
git
What does HEAD@{2} mean?
Which of these can the reflog help you recover?
Git says Deleted branch fix (was 7c6b5a4). Which command restores it?
What does ORIG_HEAD point to after a rebase?
Git Reflog Quiz
5 questions to check what you learned.
Is the reflog pushed to GitHub?
- No, it only exists in your local repository
- Yes
- Only for main
- Only with --tags
How long do reflog entries last by default?
- Forever
- One day
- About 90 days (30 for commits on no branch) before they can be removed
- Until you close the terminal
What's the safest way to recover a lost commit without moving your current branch?
- git reset --hard <hash>
- git push --force
- git clean -fd
- git branch rescued <hash>
What does the reflog record?
- Only commits
- Every move of HEAD and branch tips: commits, resets, checkouts, merges and rebases
- Only pushes
- Changes in your editor
Why is committing often good insurance?
- It makes pushes faster
- Git deletes uncommitted files nightly
- Only committed work can be recovered through the reflog
- It reduces repository size