In Git, how does git reflog differ from git log?
answer
- One walks ancestry, one walks time
- Reachability is the dividing line
- It can still see what no branch points at
- It never leaves your machine
- Entries are indexed and expire
basics
~20 sgit log walks commit ancestry from a ref, showing shared project history. git reflog lists a local journal of where HEAD or a branch has pointed over time, newest first, including commits no longer reachable from any branch.
solid answer
~50 s`git log` walks the commit graph: it starts at a ref and follows parent pointers, so it shows the history that is *reachable* and that everyone who clones the repository sees. `git reflog` shows something different — a per-ref journal of positions. Every time HEAD or a branch moves, Git appends a line recording the old id, the new id, and what caused it (`commit:`, `reset: moving to`, `checkout: moving from … to …`, `rebase (finish):`). It is ordered by when the move happened, not by ancestry, and it still lists commits that no branch points at any more, which is what makes it the recovery tool after a bad reset or rebase. Two limits matter: the reflog is purely local — it is never pushed, fetched, or copied by a clone — and its entries expire.
code
console · 5 lines$ git reflog
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
9f8e7d6 HEAD@{1}: commit: add pagination
5c4b3a2 HEAD@{2}: checkout: moving from main to feature/api
7e6d5c4 HEAD@{3}: commit: initial API skeletongo deeper
Know that git log shows project history while git reflog shows where HEAD and your branches have pointed recently, including commits that are no longer on any branch.
Explain reachability versus chronology, read the action messages in the output, and state that reflogs are per-ref, local, and subject to expiry.
Use it diagnostically: reconstruct what a teammate's scripted operation did from the action labels, and know the boundary — never-committed content is outside its reach.
Own the limits as a policy matter: a local, expiring journal is a personal undo buffer, not a team recovery guarantee, so durable safety must come from pushed refs.
## Two different questions `git log` answers *how did this commit come to be?* `git reflog` answers *where has this ref been?* **`git log`** starts from a commit and walks parent pointers backwards through the directed acyclic graph. Everything it prints is reachable from the starting ref, so the output is a property of the repository's shared history: clone the repository elsewhere and `git log main` shows the same commits. **`git reflog`** reads a journal file that Git appends to whenever a ref is updated. Each line records the previous object id, the new object id, the identity and timestamp of the update, and a human-readable action message. The order is chronological — the order in which *you* did things — and entries are addressed by index: `HEAD@{0}` is where HEAD is now, `HEAD@{1}` the position before that, and so on. ## Why the difference matters Suppose you run `git reset --hard HEAD~3`. The three commits are still in the object database, but no branch points at them, so `git log` will never show them again — they are unreachable. The reflog, however, recorded the reset, and the line for it still names the old tip. That is exactly why `git reflog` is the first command anyone suggests after work appears to vanish: it is the index of positions that ancestry-walking cannot see. ## Reading the output `git reflog` with no argument means `git reflog show HEAD`. It prints, newest first: `a1b2c3d HEAD@{0}: reset: moving to HEAD~3` `9f8e7d6 HEAD@{1}: commit: add pagination` `5c4b3a2 HEAD@{2}: checkout: moving from main to feature/api` The object id on the left is the position **after** that action. The action text tells you which command wrote the entry, which is often enough to reconstruct what happened without asking the person who did it. Each branch has its own journal too: `git reflog show main` lists only the movements of `main`, which is more precise than HEAD's journal when you want to know when a particular branch was rewritten. Under the hood `git reflog show` is a form of `git log -g`, which is why the same commit-formatting options work. ## Three properties to state in an interview 1. **Local only.** Reflogs live in your repository and are never transmitted. `git push` does not send them, `git fetch` does not receive them, and `git clone` does not copy them — a fresh clone's HEAD reflog holds a single `clone: from …` entry. Your colleague's reflog cannot rescue you and yours cannot rescue them. 2. **It expires.** Entries are pruned during garbage collection according to configured expiry windows, so the reflog is a rolling safety net measured in weeks, not an archive. 3. **It only covers refs that moved here.** If a branch never existed in your clone, no reflog entry mentions it. And content that was never committed — working-tree edits wiped by `git reset --hard`, files removed by `git clean` — was never an object, so no journal entry can restore it. ## When you would reach for each Use `git log` to review, blame, or communicate history: what changed, by whom, in what order of ancestry. Use `git reflog` when the question is operational and about your own repository: where was this branch before I rebased it, what did that reset actually move to, which commit was I on an hour ago. The two are complementary, and a candidate who describes reflog as "a log of all commits" has missed the point — it is a log of *ref movements*, and that is precisely why it can see what log cannot.
- How do you see the movements of one specific branch rather than of HEAD?`git reflog show <branch>` reads that branch's own journal, e.g. `git reflog show main`. HEAD's journal mixes in every checkout and switch, so a branch's journal is far easier to read when you want to know exactly when it was rewritten. Note that deleting a branch deletes its reflog, at which point HEAD's journal is what remains.
- Can a colleague's reflog help you recover a branch you deleted?Only if the commits ever reached their repository. Reflogs themselves are never transferred by push, fetch, or clone, so they cannot read your journal. What can help is a remote-tracking ref or a copy of the branch they already fetched, since that gives them the commit id — the recovery handle, not the journal, is what travels.
saying these in an interview costs you the question
- Describing the reflog as just another view of commit history
- Assuming the reflog is pushed to or fetched from a remote
- Expecting a fresh clone's reflog to contain the project's past
- Believing the reflog can restore never-committed working-tree edits
- Thinking reflog entries last forever