Skip to main content
CodeOath
← All posts

Git95 min total · 17 parts

Git Internals and Workflows: Branching, Merging, and Rebasing

Part 16 of 17 · ~4 min

Undoing Mistakes: The Reflog as a Safety Net

One more thing happened on Thursday, before any of the cleanup, and it is the reason this reference ends with a chapter about getting work back.

You wanted to drop the last commit — the changelog typo — and start the tidy-up from a tidy place. You meant HEAD~1. You typed:

git reset --hard HEAD~4
HEAD is now at 8e4b1a7 wip

Four commits, the API endpoints among them, and --hard wiped the working tree on the way past. git log now shows a branch that ends at wip. git status is clean. The label has moved back four commits, and as far as every ordinary Git command is concerned, most of Tuesday and Wednesday did not happen.

They did. Under the hood, Git holds onto far more than its scariest-looking commands let on — outright deletion is rarer than it appears — and the mechanism behind that is the reflog: a local, per-repository journal of every position HEAD has ever held. Every commit, checkout, merge, rebase step, reset, and branch switch appends a line to it, whether or not any branch still points at the result.

git reflog
8e4b1a7 HEAD@{0}: reset: moving to HEAD~4
3c81e06 HEAD@{1}: rebase (finish): returning to refs/heads/feature/shift-swap
3c81e06 HEAD@{2}: rebase (pick): typo in changelog
a7d92b4 HEAD@{3}: rebase (pick): Add swap offer + claim endpoints
6b3e0f1 HEAD@{4}: rebase (pick): fix the test for real
d20f5c8 HEAD@{5}: rebase (pick): fix the test

HEAD@{1} is where you were standing one move ago — the commit the reset appeared to destroy. It is right there, with its hash, along with a plain-English note about what each move was. Getting back is one command:

git reset --hard 3c81e06      # or: git reset --hard HEAD@{1}

All four commits return, and the interactive rebase can proceed on the branch you actually meant to clean up.

The same trick recovers most of the things that feel unrecoverable:

git reflog                         # find the commit from before the mistake
git reset --hard <hash>            # ...if the branch you want is the one you are on
git switch -c rescue <hash>        # ...if you would rather inspect it somewhere safe first
git reflog show feature/shift-swap # the reflog for one branch specifically, not just HEAD
  • A botched rebase. Find the hash from just before rebase (start) and reset to it. This is also what git rebase --abort does for you automatically, if you have not finished the rebase yet.
  • A deleted branch. The commits are unreferenced, not gone. Find the tip in the reflog and git switch -c a new branch at it.
  • Commits abandoned in detached HEAD. That 35f4f0c from Tuesday is still in the reflog, and Git even printed the hash at you on the way out.
  • A dropped stash. Harder, because stashes are not in HEAD's reflog, but git fsck --unreachable | grep commit will usually turn it up.

A commit is not truly gone until the reflog entry pointing at it finally expires — ninety days by default while it is still reachable, thirty once it is not — at which point garbage collection sweeps it away for good. Until that happens, "I destroyed my work" is very often false, and checking costs ten seconds.

Two limits, both important.

The reflog is local and personal. It is not pushed, not fetched, and not in a clone. It records where your HEAD has been in this repository. A fresh clone has an almost empty one, and your reflog knows nothing about what Theo did in his.

It only contains things that became commits. This is the same boundary as the reset --hard warning earlier, and it is the one that actually loses people work. An edit you never committed was never an object in Git's database, so there is nothing to find. The reflog is an excellent safety net for history you have already written down, and no safety net at all for two hours of work in the working tree. Which is the real argument for committing often: not tidiness, but that a commit is the moment your work becomes something Git can give back to you.