git reflog lists every recent position of HEAD, including "lost" commits. Find the hash from just before the mistake and run git reset --hard <hash> to restore it.Guide
Hard-reset too far, deleted a branch, lost commits? Git kept a diary. Here's how to read it.
You ran git reset --hard and went one commit too far. Or you deleted a branch
with git branch -D and realised a second later it held real work. Or you were
browsing an old commit in "detached HEAD" state (Git's way of saying you're not on any
branch), made a commit there, switched away — and now it's nowhere. The panic is the same
every time: my work is gone.
What you might see
$ HEAD is now at 3f2e1d0 Old homepage layout
$ Deleted branch login-page (was a1b2c3d). This is Git's message, not commands to run.
First, breathe — Git rarely loses anything. Almost certainly, your work is still there.
Here's the calm truth: Git doesn't delete commits right away. Commands like
reset --hard and branch -D don't erase snapshots — they only move
or remove the labels pointing at them. The commits themselves sit quietly in Git's
storage, unlisted but intact, for weeks.
Better still, Git keeps a diary. It's called the reflog (short for
"reference log"): a private, local list of every place HEAD — your current
position — has ever been. Every commit, switch, merge, pull and reset adds a line. Entries
stick around for roughly 90 days, and the reflog never leaves your machine — it isn't pushed
to GitHub, and nobody else can see it.
Mental model: commits are photos; branches are sticky notes on them. reset --hard and branch -D only peel off sticky notes — the photos stay in the shoebox. The reflog is Git's list of every photo you've recently held.
Run git reflog. The newest entries are at the top, and each line shows a short
hash (the commit's ID), where HEAD was, and what moved it — things like
commit, checkout or reset. Scan down for the entry
from just before the mistake; its message should read like your lost work.
Read the diary
$ git reflog
$ # find the entry from just before the mistake, e.g. a1b2c3d Press q to leave the list if it opens in a pager. reflog entries stick around for weeks, so recovery is usually possible.
Once you have the hash, you have two options. The direct one: move your branch back to that
commit with reset --hard. The gentler one: leave your current branch alone and
park the lost commit on a brand-new branch, so you can look it over first.
Bring the commit back
$ git reset --hard a1b2c3d # put the branch back there
$ # or park it on a new branch instead:
$ git branch rescued-work a1b2c3d Nervous? Use the git branch option — it changes nothing about where you are now, it just puts a fresh label on the lost commit.
One honest limit: the reflog only records commits. If you discarded edits
with git restore, or deleted untracked files with git clean, and
that work was never committed (or stashed), Git never took a photo
of it — there is nothing in the shoebox to find. The same goes for a file you deleted in your
editor before ever staging it. For those, your only hopes are your editor's local history or
a backup.
Tip: commit early, commit often. A rough message on a work-in-progress commit costs nothing — you can tidy it later with amend or reset — but everything committed is recoverable for weeks. Uncommitted work has no safety net.
Up next: the everyday wall everyone hits — GitHub refuses your push. What "rejected" really means and the two safe ways past it: Push Rejected.
FAQ
git reflog lists every recent position of HEAD, including "lost" commits. Find the hash from just before the mistake and run git reset --hard <hash> to restore it.git reflog, find the hash the branch tip was at, then git branch rescued-work <hash> to give it a new name.git restore or files deleted with git clean before any commit are truly gone. Commit early and often — everything committed is recoverable; see Undo Commits for the commit-level toolkit.