Skip to main content
Git & GitHub · lesson 9 of 12
Git & GitHub intermediate Lesson 9 of 12

Recovering Lost Commits with Reflog

Accidentally discard a commit with git reset --hard, watch it vanish from git log, then find and recover it with git reflog.

By SkillByExample · Published

git reflog recovery

git reset --hard looks destructive because the commit disappears from git log immediately. It isn’t gone — the reflog remembers every place HEAD has pointed, and this lesson uses it to undo a real mistake.

1) Commit something, then discard it by mistake

$ # ...edit scratch.py, add total()...
$ git commit -am "Add total() helper"
$ git log --oneline -1
3cb083d Add total() helper
$ git reset --hard HEAD~1
$ git log --oneline -1
73f7789 Add scratch calculation feature

3cb083d is gone from git log — as far as the normal history view is concerned, it never happened.

2) The reflog remembers anyway

$ git reflog
73f7789 HEAD@{0}: reset: moving to HEAD~1
3cb083d HEAD@{1}: commit: Add total() helper
73f7789 HEAD@{2}: commit (amend): Add scratch calculation feature
26b7ef1 HEAD@{3}: rebase (finish): returning to refs/heads/main

Every move HEAD made on this machine is logged, most recent first — including the reset itself. HEAD@{1} is exactly where HEAD pointed right before the reset: 3cb083d, the commit that seemed to vanish.

3) Recover it

$ git reset --hard HEAD@{1}
$ git log --oneline -2
3cb083d Add total() helper
73f7789 Add scratch calculation feature

Another reset --hard, this time aimed at the reflog entry instead of a branch or commit hash, puts main right back where it was. Nothing was actually lost — the commit object stayed on disk the whole time; only the branch pointer had moved away from it.

Practice

  1. Run git reflog after a git commit --amend (from the rewriting-history lesson) and find both the old and new commit listed — amend abandons a commit the same way reset does, and it’s recoverable the same way.

  2. Use git branch recovered-work 3cb083d (a commit hash from the reflog, not HEAD@{1}) to create a new branch pointing at a “lost” commit instead of moving main back — useful when you don’t want to disturb your current branch’s tip.

    Solution
    $ git branch recovered-work 3cb083d
    $ git log --oneline recovered-work -1
    3cb083d Add total() helper

    main stays wherever it was; the lost commit is now reachable from a new branch.

  3. Run git show HEAD@{2} to inspect a reflog entry from further back without resetting anything — reflog entries work anywhere a commit reference is expected.

  4. Deliberately lose an uncommitted change (edit a file, don’t commit, then git reset --hard) and confirm git reflog does not help recover it — it only tracks where HEAD and branches pointed, not working-directory content that was never committed.

  5. Run git reflog show <branch-name> (rather than plain git reflog, which defaults to HEAD) to see the movement history of a specific branch ref.

Frequently Asked Questions

If git log doesn't show the commit anymore, is it actually deleted?
Not immediately. Git only stops pointing any branch at it — the commit object stays on disk until garbage collection eventually removes genuinely unreachable objects, typically after a 90-day grace period (gc.reflogExpire). Within that window, the reflog gives you a path back to it.
What exactly is the reflog tracking?
Every movement of HEAD on your local machine: commits, resets, checkouts, merges, rebases. It's a personal, local-only log — it isn't pushed, isn't shared with clones, and isn't part of the commit graph itself.
Why HEAD@{1} instead of a commit hash?
HEAD@{1} means "where HEAD pointed one move ago," read straight from the reflog — often faster to grab than copying a hash out of git reflog's output. Both refer to the same commit here; @{n} is just reflog-relative shorthand.
Does every git reset --hard risk losing work permanently?
It risks losing uncommitted work permanently (nothing to recover from — it was never a commit). Committed work, even after --hard, is recoverable via reflog until garbage collection — which is exactly what this lesson demonstrates.