Lesson 5 of 6 in Undoing Things
Rescuing lost work
Story: The Loose Cannon swears that branch is gone for good. The agency has a long memory.
Committed work is hard to lose. A reset, an amend or a deleted branch takes commits off a branch, but the commits themselves stay in the repository. What's gone is a name that points at them. In the Live Graph they turn faded, unless another branch still has them.
To get them back, you need to find them. That's what the reflog is for.
The reflog
Every time HEAD moves, git writes a line in the reflog: when you commit, switch, reset, amend, merge or revert. git reflog lists those lines, newest first.
Say you made three commits on main and reverted the last one. Then you made a branch dark-mode with one commit, switched back to main and deleted dark-mode:
$ git reflog
99af3e7 (HEAD -> main) HEAD@{0}: checkout: moving from dark-mode to main
df79e5b HEAD@{1}: commit: Darken the footer
99af3e7 (HEAD -> main) HEAD@{2}: checkout: moving from main to dark-mode
99af3e7 (HEAD -> main) HEAD@{3}: revert: Revert "Add the banner"
0067ace HEAD@{4}: commit: Add the banner
984ebf9 HEAD@{5}: commit: Style the heading
a0ec373 HEAD@{6}: commit (initial): Add the home page
Each line shows the commit HEAD pointed at, a name for that moment, and what happened. HEAD@{0} is now, HEAD@{1} is one move ago, and HEAD@{2} two moves ago. Switching between branches is called checkout here, even when you used git switch.
You can use these names anywhere git expects a commit: git reset --hard HEAD@{1}, git branch rescued HEAD@{3}, git merge HEAD@{2}. git reflog only reads, so running it is always safe.
Each branch also keeps a reflog of its own. main@{1} means where main was one move ago, which is what Moving a branch back used to undo a reset.
Undo a reset
A hard reset moved main back by mistake? main@{1} is where it was just before:
git reset --hard main@{1}
The same works for an amend: main@{1} is the commit as it was before you amended it.
Bring back a deleted branch
Deleting a branch deletes its own reflog too, so dark-mode@{1} no longer works. But HEAD was on that branch while you made its commits, so HEAD's reflog still has them. In the reflog above, HEAD@{1} is commit: Darken the footer, the last commit made on dark-mode.
Put a branch back on it:
git branch dark-mode HEAD@{1}
git branch <name> <commit> creates a branch at any commit, not only the one you're on. git switch -c <name> <commit> does the same and switches to it.
Read it right before you use it
The numbers shift. Every move adds a line at the top, so after your next commit, what was HEAD@{1} becomes HEAD@{2}. Run git reflog just before you use one of its names, and pick the line by what it says happened, not by its number.
What the reflog can't do
- It only rescues commits. The reflog records where
HEADand your branches pointed. An edit you never committed has no line in it, so the reflog can't bring it back. - It's yours alone. It lives in your repository and isn't pushed or cloned. A teammate's reflog knows nothing about your moves.
- It doesn't last for ever. On a real machine, git expires old entries in the end: by default after 30 days for commits no branch can reach, and 90 days for the rest. Rescue lost work soon.
New commands
git reflog
Explainer: The reflog remembers where you've been
Graph as text
project: your repo, you are here
- HEAD → main at 3997c22 "Write day 3"
Branches and tags
- main at 3997c22 "Write day 3"
- photos at a36c656 "List the photos"
Commits, newest first
- a36c656 "List the photos"; parent 7cfc0e4; refs: photos
- 3997c22 "Write day 3"; parent d80b67d; refs: HEAD → main
- d80b67d "Write day 2"; parent 7cfc0e4
- 7cfc0e4 "Write day 1"; no parent
Challenge 1 of 3
Story: Two days of the field journal, wiped in one command. Wind them back in.
Someone ran git reset --hard HEAD~2 on main by mistake, and the commits Write day 2 and Write day 3 vanished from it. Put main back exactly where it was before the reset, with nothing left to commit.
Unlocks after Branching & Merging.
Terminal
Unlocks after Branching & Merging.
This Lesson can be played once Branching & Merging is complete. Its text and Explainer are open to everyone.