git reflog is the Git command you use when commit history looks broken after a reset, amend, rebase, branch deletion, or checkout. It records where references such as HEAD, local branches, remote-tracking branches, and stash pointed recently inside your local repository.
If you ran a destructive command and need the shortest recovery path, start here:
git reflog
git reset --hard HEAD@{1}Use HEAD@{1} only when the reflog entry at that position is the commit you want. In real repositories, always inspect the reflog output first and choose the correct entry.
This article uses tested output from a local Git lab. The examples were run with Git 2.48.1 on June 9, 2026.
What is Git Reflog?
Git reflog means reference log. A reference is a pointer such as HEAD, main, feature/login, origin/main, or stash. Whenever Git moves one of these references, Git can record the old and new position in a reflog.
That makes reflog different from normal commit history:
| Command | What it shows | Best use |
|---|---|---|
git log |
Commits reachable from the current branch | Review normal project history |
git reflog |
Recent movements of HEAD and other refs |
Recover commits hidden by reset, amend, rebase, checkout, or branch deletion |
git reflog --all |
Reflog entries from all refs that still have reflogs | Search across branches, remote-tracking refs, and stash |
git reflog show <ref> |
Reflog for one ref | Inspect a specific branch, remote-tracking branch, or stash |
The official Git documentation describes reflogs as local records of when branch tips and other references were updated. It also notes that expressions like HEAD@{2} and main@{one.week.ago} can be used to refer to older ref positions.
Git Reflog Recovery Cheat Sheet
| Problem | Command pattern |
|---|---|
| See recent HEAD movements | git reflog |
| See reflog with timestamps | git reflog --date=iso |
| Recover after reset | git reset --hard HEAD@{1} |
| Recover by exact hash | git reset --hard <commit-hash> |
| Recover deleted branch | git branch <branch-name> <commit-hash> |
| Search all reflogs | git reflog --all |
| Show one branch reflog | git reflog show main |
| Show stash reflog | git reflog show stash |
| List refs with reflogs | git reflog list |
| Test full ref reflog | git reflog exists refs/heads/main |
| Preview reflog pruning | git reflog expire --dry-run --verbose --expire=now --all |
Tested Lab Setup
The following test repository was created in /tmp so the commands could be verified safely without touching a real project.
git --version
mkdir reflog-demo
cd reflog-demo
git init -b main
git config user.name "GoLinuxCloud"
git config user.email "author@golinuxcloud.test"Tested output:
git version 2.48.1
Initialized empty Git repository in /tmp/git-reflog-lab.h8jLo3/reflog-demo/.git/Next, three commits were created:
printf 'one\n' > app.txt
git add app.txt
git commit -m "initial commit"
printf 'two\n' >> app.txt
git add app.txt
git commit -m "add second line"
printf 'three\n' >> app.txt
git add app.txt
git commit -m "add third line"Tested output:
[main (root-commit) 1652683] initial commit
1 file changed, 1 insertion(+)
create mode 100644 app.txt
[main 42c9538] add second line
1 file changed, 1 insertion(+)
[main a535509] add third line
1 file changed, 1 insertion(+)The commit history before any recovery test looked like this:
git log --oneline --decorateTested output:
a535509 (HEAD -> main) add third line
42c9538 add second line
1652683 initial commitGit Reflog Example After Reset
A common search query is git reflog reset or git reset reflog. Both usually mean: "I ran reset and want my commit back."
In the test repo, the latest commit was removed from visible branch history using a hard reset:
git reset --hard HEAD~1Tested output:
HEAD is now at 42c9538 add second lineAt this point, git log would no longer show commit a535509. Reflog still records where HEAD was before the reset:
git reflog --date=isoTested output:
42c9538 HEAD@{2026-06-09 08:45:26 +0530}: reset: moving to HEAD~1
a535509 HEAD@{2026-06-09 08:45:26 +0530}: commit: add third line
42c9538 HEAD@{2026-06-09 08:45:26 +0530}: commit: add second line
1652683 HEAD@{2026-06-09 08:45:26 +0530}: commit (initial): initial commitThe lost commit is the entry before the reset: a535509.
You can restore it by resetting back to the reflog entry:
git reset --hard HEAD@{1}
git log --oneline --decorate -3Tested output:
HEAD is now at a535509 add third line
a535509 (HEAD -> main) add third line
42c9538 add second line
1652683 initial commitYou can also use the commit hash directly:
git reset --hard a535509Tested output:
HEAD is now at a535509 add third lineIn a shared repository, be careful before using git reset --hard on commits that were already pushed. For pushed history, compare this with git revert and git push force behavior before rewriting remote history.
Recover an Amended Commit with Git Reflog
git commit --amend replaces the latest commit with a new commit hash. The old commit disappears from normal git log, but reflog records the movement.
The test amended the latest commit message:
git commit --amend -m "add third line with better message"Tested output:
[main a7da451] add third line with better message
Date: Tue Jun 9 08:45:26 2026 +0530
1 file changed, 1 insertion(+)Now inspect the latest reflog entries:
git reflog --date=iso -4Tested output:
a7da451 HEAD@{2026-06-09 08:45:26 +0530}: commit (amend): add third line with better message
a535509 HEAD@{2026-06-09 08:45:26 +0530}: reset: moving to HEAD@{1}
42c9538 HEAD@{2026-06-09 08:45:26 +0530}: reset: moving to HEAD~1
a535509 HEAD@{2026-06-09 08:45:26 +0530}: commit: add third lineThe amended commit is a7da451, and the earlier commit was a535509. To recover the pre-amend commit without changing the current branch, create a branch at the old hash:
git branch before-amend a535509
echo "before_amend_exit=$?"
git branch --list before-amendTested output:
before_amend_exit=0
before-amendIf your goal is only to fix the last commit message, see git commit amend examples and change Git commit message.
Recover a Deleted Branch with Git Reflog
Reflog can also help when a local branch was deleted before you pushed or merged its work.
In the test repo, a branch was created, committed, checked out back to main, and then deleted:
git switch -c feature/login
printf 'feature\n' > feature.txt
git add feature.txt
git commit -m "add login feature"
git switch main
git branch -D feature/loginTested output:
Switched to a new branch 'feature/login'
[feature/login 3e4697d] add login feature
1 file changed, 1 insertion(+)
create mode 100644 feature.txt
Switched to branch 'main'
Deleted branch feature/login (was 3e4697d).If you still have the deletion message, the branch tip is already visible: 3e4697d. If not, search all reflogs:
git reflog --all --date=iso | head -n 8Tested output:
a7da451 refs/heads/main@{2026-06-09 08:45:26 +0530}: commit (amend): add third line with better message
a535509 refs/heads/main@{2026-06-09 08:45:26 +0530}: reset: moving to HEAD@{1}
42c9538 refs/heads/main@{2026-06-09 08:45:26 +0530}: reset: moving to HEAD~1
a535509 refs/heads/main@{2026-06-09 08:45:26 +0530}: commit: add third line
42c9538 refs/heads/main@{2026-06-09 08:45:26 +0530}: commit: add second line
1652683 refs/heads/main@{2026-06-09 08:45:26 +0530}: commit (initial): initial commit
a7da451 HEAD@{2026-06-09 08:45:26 +0530}: checkout: moving from feature/login to main
3e4697d HEAD@{2026-06-09 08:45:26 +0530}: commit: add login featureCreate a new branch at the lost commit:
git branch recovered-login 3e4697d
git branch --listTested output:
* main
recovered-loginVerify the recovered branch points to the commit that added the file:
git show --stat --oneline recovered-login --Tested output:
3e4697d add login feature
feature.txt | 1 +
1 file changed, 1 insertion(+)If you need to switch to that branch after recovery, use git checkout or git switch.
Show Reflog for a Specific Branch
By default, git reflog shows the HEAD reflog. To inspect a specific branch, use git reflog show <branch>.
git reflog show main --date=iso | head -n 5Tested output:
a7da451 main@{2026-06-09 08:45:26 +0530}: commit (amend): add third line with better message
a535509 main@{2026-06-09 08:45:26 +0530}: reset: moving to HEAD@{1}
42c9538 main@{2026-06-09 08:45:26 +0530}: reset: moving to HEAD~1
a535509 main@{2026-06-09 08:45:26 +0530}: commit: add third line
42c9538 main@{2026-06-09 08:45:26 +0530}: commit: add second lineThis is useful when multiple branches are involved and HEAD moved through several checkouts.
For remote-tracking branches, the same pattern works if your local clone has a reflog for that ref, such as origin/main. This is helpful after a force push because your local clone may remember where the remote-tracking ref pointed before it moved.
Git Reflog List and Exists
Git can list refs that currently have reflogs:
git reflog listTested output:
HEAD
refs/heads/main
refs/heads/recovered-loginWhen testing whether a reflog exists, use the full ref name. In this lab, the full ref worked, but the short branch name did not:
git reflog exists refs/heads/main
echo "exists_refs_heads_main_exit=$?"
git reflog exists main
echo "exists_main_exit=$?"Tested output:
exists_refs_heads_main_exit=0
exists_main_exit=1An exit code of 0 means the reflog exists. A non-zero exit code means Git did not find a reflog for that exact ref argument.
Use HEAD@{n} and HEAD@{time}
Reflog entries can be referenced by position:
| Syntax | Meaning |
|---|---|
HEAD@{0} |
Current recorded HEAD position |
HEAD@{1} |
Previous recorded HEAD position |
main@{1} |
Previous recorded position of main |
HEAD@{1.minute.ago} |
Where HEAD pointed around one minute ago, if the reflog goes back that far |
main@{yesterday} |
Where main pointed yesterday, if available |
The test confirmed HEAD@{0} resolves to the current commit:
git rev-parse --short HEAD
git rev-parse --short 'HEAD@{0}'Tested output:
a7da451
a7da451You can also compare two reflog positions:
git diff --stat main@{1} main@{0}In the test repo this produced no output because the selected reflog states did not change file content in that comparison.
Git Reflog for Stash
Stash has its own ref, so you can inspect stash reflog entries too.
printf 'temporary\n' >> app.txt
git stash push -m "temporary app change"
git reflog show stash --date=isoTested output:
Saved working directory and index state On main: temporary app change
a0ba40e stash@{2026-06-09 08:45:26 +0530}: On main: temporary app changeThe normal stash list also shows the saved entry:
git stash listTested output:
stash@{0}: On main: temporary app changeFor more stash workflows, see Git stash examples.
Git Reflog Expiration and Limitations
Reflog is powerful, but it is not permanent backup.
Important limits:
- Reflog is local to your clone; it is not pushed to GitHub or GitLab.
- Reflog usually cannot recover changes that were never committed or stashed.
- Reflog entries can expire and be pruned by Git garbage collection.
- If a commit is no longer reachable and its reflog entry expires, Git may eventually remove the object.
- A different clone may have a useful reflog even when your clone does not.
Common default expiration behavior is:
| Setting | Common default | Meaning |
|---|---|---|
gc.reflogExpire |
90 days | Keeps reachable reflog entries |
gc.reflogExpireUnreachable |
30 days | Keeps reflog entries not reachable from the current tip |
You can preview reflog expiration without deleting anything:
git reflog expire --dry-run --verbose --expire=now --all | head -n 10Tested output:
would prune commit (initial): initial commit
would prune commit: add second line
would prune commit: add third line
would prune reset: moving to HEAD~1
would prune reset: moving to HEAD@{1}
would prune commit (amend): add third line with better message
would prune checkout: moving from main to feature/login
would prune commit: add login feature
would prune checkout: moving from feature/login to main
would prune reset: moving to HEADDo not run expiration or garbage collection commands casually on a repository where you still need recovery options. Keep backups for important projects.
Git Reflog vs Git Log
Use git show and log commands when the commit is still part of normal branch history. Use reflog when the commit disappeared from normal history because a reference moved.
| Scenario | Use git log | Use git reflog |
|---|---|---|
| Review normal commits on current branch | Yes | Sometimes |
| Find commit hidden by hard reset | No | Yes |
| Find pre-amend commit | No | Yes |
| Find branch tip after branch deletion | Usually no | Yes, if recently referenced |
| Inspect branch switching history | No | Yes |
| Recover never-committed file edits | No | Usually no |
git reflog show is closely related to this command:
git log -g --abbrev-commit --pretty=oneline -3Tested output:
a7da451 HEAD@{0}: reset: moving to HEAD
a7da451 HEAD@{1}: checkout: moving from feature/login to main
3e4697d HEAD@{2}: commit: add login featureGit Reflog Recovery Checklist
Use this checklist before changing history again:
- Run
git reflog --date=isoand identify the exact entry you need. - Prefer creating a recovery branch at the commit hash before resetting anything.
- Use
git reflog --allif the normal HEAD reflog does not show the missing commit. - Check branch-specific reflog output when multiple branches were involved.
- Act quickly because reflog entries can expire.
Common Mistakes
Using HEAD@{1} without checking it
HEAD@{1} often means the previous HEAD position, but not always the one you want. If you checked out branches, amended commits, stashed changes, or reset multiple times, inspect git reflog first.
Expecting reflog to recover uncommitted work
Reflog tracks ref movement. If a file was never committed, stashed, or saved elsewhere, reflog usually cannot restore it.
Searching only HEAD reflog for a branch issue
If git reflog does not show the commit, try git reflog --all or a branch-specific reflog such as git reflog show main.
Waiting too long
Reflog entries expire. If you need to recover a commit, create a branch at that commit as soon as you find it.
Confusing git reflogging with git reflog
There is no standard Git command named git reflogging. The command is git reflog; "reflogging" is just a casual way people describe using reflog.
Frequently Asked Questions
1. What is git reflog?
2. How do I use git reflog to recover after git reset --hard?
3. What is the difference between git log and git reflog?
4. Can git reflog recover a deleted branch?
5. Is git reflog pushed to GitHub or GitLab?
6. How long does git reflog keep entries?
7. Can git reflog recover uncommitted changes?
8. Is git reflogging a command?
Summary
Git reflog is a local safety record for reference movement. It helps recover commits after git reset --hard, restore pre-amend commits, locate deleted branch tips, inspect branch-specific history, and review stash movement.
The safest habit is to create a recovery branch before changing your current branch again. In the test lab, this preserved the recovered branch tip:
git branch recovery 3e4697d
echo "recovery_exit=$?"
git branch --list recovery recovered-loginTested output:
recovery_exit=0
recovered-login
recoveryCreating a recovery branch is often safer than immediately resetting your current branch. After you verify the recovered commit, you can merge, cherry-pick, or reset depending on your workflow.

