Git Reflog: Reading the Local History of References
Learn how reflogs record local reference updates, how to inspect HEAD and branch reflogs, and how to use reflog-based revision names to identify earlier reference values.
Advanced
Learner goal
By the end of this lesson, you should be able to inspect a reflog, distinguish a HEAD reflog from a branch reflog, resolve a reflog-based revision such as `main@{1}`, and explain why a reflog is local reference history rather than the commit graph itself.
reflog → local record of ref updates
HEAD reflog → also records branch switching
main@{1} → previous value of the local main refQuick check
What does a reflog primarily record?
A branch tip has moved locally.The reflog records the reference movement as a local entry.
A reflog is reference history, not commit history
Git already has a commit graph: commits point to parent commits. A reflog records changes to a reference's value over time. The same commit can therefore appear in a reflog more than once, and a reflog entry can describe a movement that did not create a new commit.
This distinction matters after operations such as reset, rebase, branch switching, or other reference updates. The reflog answers a question such as “what did this local reference point to earlier?” rather than “which commits are ancestors of this commit?”
git log --oneline --decorate --graph -5
git reflog main -5Quick check
Which statement correctly distinguishes a reflog from the commit graph?
You are comparing two kinds of history information.One shows reference movement; the other shows commit ancestry.
Inspect the HEAD reflog
`git reflog` and `git reflog show` display the reflog for `HEAD` by default. The official documentation also specifies that the `HEAD` reflog records branch switching, which makes it useful for answering “where was HEAD immediately before this checkout?”
git reflog
git reflog show HEAD -5
git reflog HEAD -5Quick check
What extra kind of activity does the HEAD reflog record?
The learner switches from one branch to another.The HEAD reflog gains a checkout entry describing the move.
Inspect a branch reflog
A local branch can have its own reflog. `git reflog main` shows the local history of the `main` reference. A branch reflog changes when the branch tip changes; merely switching away from or back to the branch is recorded in the HEAD reflog, not as a movement of the branch tip itself.
git reflog main -5
git reflog exists refs/heads/mainQuick check
After switching from `main` to `feature` without moving either branch tip, which reflog is expected to record the switch?
main and feature still point at the same commits as before the checkout.The HEAD reflog records the checkout event; the branch reflog tips have not moved.
Use reflog revision names
The official revision syntax lets you refer to an earlier value of a reference. `main@{1}` means the previous reflog value of `main`, while `HEAD@{2}` means the value HEAD had two reflog moves ago. A date form such as `main@{yesterday}` asks for the value of that local reference at the specified time, provided the reference has a reflog.
git rev-parse 'main@{1}'
git show --no-patch --format='%H %s' 'main@{1}'
git rev-parse 'HEAD@{2}'Quick check
What does `main@{1}` identify?
main currently points at commit C and its reflog has a prior value B.`main@{1}` resolves to the earlier value B.
Quick check
Why can `HEAD@{1}` and `main@{1}` resolve to the same commit in a simple repository?
HEAD is attached to main and main has just moved.Both revision names can resolve to the same commit object even though they refer to different refs.
Read a previous value after a reference move
A reflog becomes particularly useful when a reference has moved. In a disposable repository, you can move `main` backward with `git reset --hard`, then inspect `main@{1}` to identify the branch tip that existed immediately before that reset. This lesson stops at identification and inspection; the next curriculum lesson owns actual recovery of abandoned commits.
before=$(git rev-parse HEAD)
git reset --hard HEAD~1
git reflog main -3
git rev-parse 'main@{1}'
git show --no-patch --format='%H %s' 'main@{1}'Quick check
After a reset that moved `main` backward, what is the key use of `main@{1}`?
main has moved and the previous tip is no longer the current branch tip.The reflog still provides a revision name for the earlier local value.
Reflogs have an existence and retention boundary
`git reflog list` lists references that currently have corresponding reflogs, and `git reflog exists <ref>` tests whether a reflog exists. The official documentation also defines reflog expiration: reachable entries default to 90 days and entries that are unreachable from the current tip default to 30 days, through the corresponding `gc.reflogExpire` and `gc.reflogExpireUnreachable` settings.
git reflog list
git reflog exists refs/heads/main
git config --get gc.reflogExpire
git config --get gc.reflogExpireUnreachableQuick check
Why should you avoid treating a reflog entry as permanent storage?
The learner is planning recovery from an old local reference value.The correct expectation is that reflog retention is bounded by expiration policy.
Local scope matters
The official Git documentation describes reflogs as local repository information. A reflog therefore describes the reference movements known in that particular repository. It is not the shared commit history of all clones, and it should not be confused with a remote branch's history on another repository.
Repository A reflog → records local ref movements in A
Repository B reflog → records local ref movements in B
Commit graph → shared by object transfer when commits are actually transferredQuick check
What is the correct scope for a reflog?
Two repositories contain related commits but have different local reference movement histories.Each repository can have different reflog information because the logs are local.
Practice what you learned
Use the dedicated Git code-completion exercise for this lesson.
Quick check
What should your final verification prove?
The branch tip has been moved locally in a disposable repository.The reflog and revision selector identify the earlier branch tip without changing the remote or creating a new commit.
Official-source boundary
This lesson uses only official Git project documentation: `git-reflog` for reflog behavior and subcommands, `gitrevisions` for reflog-based revision syntax, and the official Git glossary/user manual for the local-history definition. The live official `gitrevisions` documentation is Git 2.56.0; the live `git-reflog` manual is unchanged through Git 2.56.0 and reports its last manual update in 2.51.1. Foxipa's local verifier is Git 2.47.3, so execution evidence is reported for that installed executable rather than silently generalized to every Git release.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.