The Undo Button Nobody Uses: `git reflog`
An interactive rebase drops a commit you actually needed, and git log no longer shows it. It isn't gone — git reflog remembers every HEAD you've ever had, including the one from thirty seconds ago.

You're cleaning up a hotfix branch before opening the PR. An interactive rebase seems like the right tool — squash a couple of commits, tidy the messages. You edit the todo list, save, and git log comes back one commit short. The regression test you added is nowhere to be found. git log, git status, git show — all clean, all show no trace of it.
It isn't gone. Git doesn't delete commits just because no branch points at them anymore. It stops displaying them, which feels the same in a moment of panic but is a very different problem to have.
What actually happened
A hotfix branch, three commits deep:
git log --oneline
# 981ffe8 log timeout duration for observability
# dc86bc5 add regression test for payment timeout
# 8552d69 guard against nil pointer in payment retry
# bdd86dc base commitAn interactive rebase to tidy things up drops the middle commit by mistake — easy to do when you're rewording lines in an editor and delete the wrong one:
git rebase -i bdd86dcgit log --oneline
# c7912b9 log timeout duration for observability
# 8552d69 guard against nil pointer in payment retry
# bdd86dc base commitdc86bc5, the regression test commit, has vanished from history. The branch now has two commits where it used to have three, and there's no menu, no trash can, no obvious way to get it back through the commands you'd normally reach for.
Ask git what it actually did
Every time HEAD moves — a commit, a checkout, a rebase step, a reset — git records it in the reflog. It's a private log of your own movements through the repository, kept for 90 days by default and never pushed anywhere.
git reflogc7912b9 HEAD@{0}: rebase (finish): returning to refs/heads/hotfix/payment-timeout
c7912b9 HEAD@{1}: rebase (pick): log timeout duration for observability
8552d69 HEAD@{2}: rebase (start): checkout bdd86dc
981ffe8 HEAD@{3}: commit: log timeout duration for observability
dc86bc5 HEAD@{4}: commit: add regression test for payment timeout
8552d69 HEAD@{5}: commit: guard against nil pointer in payment retry
bdd86dc HEAD@{6}: checkout: moving from main to hotfix/payment-timeout
bdd86dc HEAD@{7}: commit (initial): base commitRight there at HEAD@{4}: dc86bc5, "add regression test for payment timeout." The commit object was never deleted — only the branch pointer that used to lead to it moved away during the rebase.
Bringing it back
The commit still exists, so you can cherry-pick it straight back onto the branch:
git cherry-pick dc86bc5[hotfix/payment-timeout d933c82] add regression test for payment timeout
1 file changed, 1 insertion(+)
create mode 100644 regression_test.txtgit log --oneline
# d933c82 add regression test for payment timeout
# c7912b9 log timeout duration for observability
# 8552d69 guard against nil pointer in payment retry
# bdd86dc base commitThe regression test is back, with its original message and content intact. It landed on top rather than in its original position — that's fine for a hotfix branch you're about to squash and merge anyway; if you need the exact original order, git rebase -i again to move it into place.
When this saves you
Reflog is the answer to almost every "I think I just destroyed my work" moment:
- A bad
git reset --hard. The commits you had before the reset are still reachable from the reflog entry right before it. - An amend that overwrote the wrong commit. The pre-amend commit is sitting one entry back.
- A rebase or merge you aborted halfway through and now can't remember the starting point of.
git reflogshows exactly whereHEADwas before you started.
The one thing reflog can't rescue is a commit that's aged out of it (90 days is the default gc.reflogExpire) and has since been garbage collected — or one that was never committed at all, just edited in your working tree and overwritten. Reflog tracks commits, not uncommitted changes.
Next time git log looks wrong after a rebase, don't assume the work is gone. Run git reflog first — it almost always remembers what you did five minutes ago, even when you don't.