Reflog recovery · 2026-07-15

How to undo git reset --hard.

You ran git reset --hard, and commits you wanted are gone from the branch. In almost every case they are not actually gone. Git keeps a private log of everywhere HEAD has pointed, called the reflog, and the commit you reset away from is still sitting there. This is how to get it back, and how to know when you cannot.

The short answer

Find where HEAD was before the reset with git reflog, then move your branch back to it.

git reflog
# Find the line for the state you want, e.g. HEAD@{1}
git reset --hard HEAD@{1}

HEAD@{1} means "where HEAD pointed one move ago", which for a fresh reset is the commit you just left. If the good state is further back, use the number next to it in the reflog output, or copy the commit SHA and reset to that instead: git reset --hard 9b7c4e2. One important caveat first, because it decides whether the rest of this article can help you.

Committed work versus uncommitted work

Reflog recovers commits. If the work you lost was committed before the reset, you are in good shape and the steps below will bring it back. If the work was never committed, only staged or edited in the working tree, then git reset --hard overwrote those files and the reflog has nothing to offer, because there was no commit to point at.

There is a partial exception: content that was ever staged with git add exists as a loose object in the repository, and git fsck --lost-found can sometimes surface it. That path is covered in the companion guide linked at the end. For committed work, keep reading.

Step by step

Before anything, stop running commands that move refs. Every extra reset, rebase, or checkout adds noise to the reflog and can push the entry you need further down. Inspect first, act once.

1. Read the reflog

Run git reflog. Each line is a past position of HEAD with an index like HEAD@{2} and a short SHA. The entry describing the reset (its message starts with reset:) is the move you want to undo; the line just above it is where you were.

2. Confirm the commit

Run git show HEAD@{1} or git show <sha> to verify that entry really holds the work you lost before you move anything.

3. Recover safely

The safest move is a rescue branch: git branch rescue <sha>. Nothing on your current branch changes, and the recovered commit now has a name you cannot lose.

The full sequence

Here is a complete, safe recovery. It looks at the reflog, verifies the commit, and rescues it into a branch instead of resetting in place, so a wrong guess costs nothing:

$ git reflog
9b7c4e2 HEAD@{0}: reset: moving to HEAD~3
4d3a1f8 HEAD@{1}: commit: add checkout validation
a1b2c3d HEAD@{2}: commit: wire payment provider
...

# Verify HEAD@{1} is the work you want
$ git show HEAD@{1}

# Rescue it into a branch without touching your current one
$ git branch rescue-lost-work HEAD@{1}

# When you are sure, move your branch back
$ git reset --hard HEAD@{1}

If you would rather just jump straight back and skip the rescue branch, git reset --hard HEAD@{1} on its own is enough. The rescue branch only exists so that a mistaken reset has an undo of its own.

What reset --hard actually did

git reset --hard <target> does three things: it moves the current branch to <target>, it makes the index match, and it overwrites the working tree to match. The commits you moved away from are not deleted. They simply become unreferenced, and Git keeps unreferenced commits around for a while (the default is at least 30 days for unreachable objects, 90 for reachable-then-abandoned ones) before garbage collection can remove them. That grace window is why reflog recovery works, and why acting sooner is better than acting later.

What reflog does not guarantee

The reflog is local to your clone and time-limited. It does not exist on a fresh clone, it is pruned over time, and it cannot restore working-tree edits that were never committed or staged. If you have already run git gc --prune=now after the reset, the objects may be gone for good. Treat reflog as a strong safety net, not a backup system.

FluxGit reflog recovery

Undo a hard reset without reading the reflog by hand.

FluxGit puts reflog movement and Flux restore points on one Safety Timeline, so the commit you reset away from is a labelled entry you can preview and restore, not a short SHA you have to decode. Destructive operations capture a restore point first, and a safety stash protects uncommitted work before a hard reset runs. FluxGit v0.3.1 is a signed and notarized macOS build, free to download and free on public repositories, with Windows and Linux by invite.

Related: Recover lost Git work with reflog · My AI agent deleted my code, now what · How to recover a deleted Git branch