Undo a git reset --hard and get your commits back
I ran git reset --hard and lost my commits — how do I undo it?
Short answer
Committed work is almost never really gone. git reflog lists every position HEAD has held, including the one just before your reset, so you can jump straight back to it with git reset --hard HEAD@{1}. Uncommitted changes that the reset wiped are a different story — those are only recoverable if they had been staged at some point.
git reflog
git reset --hard HEAD@{1}
Find the position from just before the reset and return to it
Does this match your situation?
- You ran git reset --hard and commits vanished from git log.
- A branch suddenly points at a much older commit.
- You reset to the wrong commit and want to go back to where you were.
Step-by-step fix
Open the reflog immediately
The reflog is a local journal of every move HEAD has made — commits, checkouts, resets, merges, rebases. Your pre-reset position is still listed there even though no branch points to it any more. Do this before running any other Git command so the entry you want stays near the top.
step 1git reflogOutput looks like: a1b2c3d HEAD@{0}: reset: moving to HEAD~3 / f4e5d6c HEAD@{1}: commit: Add save system
Identify the entry from just before the reset
Read down the list until you find the reset itself — the entry directly below it is where you were standing beforehand. Confirm you've got the right one by inspecting it before you move anything.
step 2git show HEAD@{1} git log HEAD@{1} --oneline -5Move your branch back to that commit
Once you're sure, point the branch at the recovered commit. Using the explicit hash rather than HEAD@{1} is safer, because the reflog shifts every time HEAD moves.
step 3git reset --hard f4e5d6cPrefer the raw hash over HEAD@{1} — the numbering changes as soon as you run another command.
Or recover onto a fresh branch instead
If you'd rather not disturb the current branch, create a new one at the lost commit. This is the risk-free option: nothing you already have moves, and you can compare the two before deciding.
step 4git branch recovered-work f4e5d6c git switch recovered-work
Why this works
git reset --hard doesn't delete commits — it only moves a branch pointer and overwrites your working directory. The commits it moved away from remain in .git/objects, unreferenced but intact. The reflog keeps a record of every value each reference has held, for 90 days by default, which is exactly the map you need to point a branch back at them. The part reset --hard genuinely destroys is uncommitted working-directory content, because that was never written to the object database in the first place — unless you had staged it, in which case a dangling blob survives.
If that didn’t work
- If the reflog is empty or missing the entry, run git fsck --lost-found and look through the dangling commits.
- Check whether the commits were ever pushed — git fetch origin and look at origin/your-branch.
- Look for the work in another clone, a CI job's checkout, or a colleague's fetch of your branch.
How to stop it happening again
- Use git reset --keep instead of --hard: it refuses to run if it would overwrite uncommitted changes.
- Commit or stash before any reset — then the worst case is a one-line reflog fix.
- Create a throwaway safety branch before risky operations: git branch backup-before-rebase.
Commands used in this guide
git reflogThe undo history for everything - the single most important recovery command.
git resetMove the current branch pointer, optionally rewriting the index and your files.
git fsckScan the object database for orphaned commits and blobs the reflog no longer lists.
git branchList, create, rename and delete branches.
Still stuck?
Search the full command reference and every other rescue guide — there are 56 of them, covering everything from detached HEAD to force-push disasters.
Browse all guides →Frequently asked questions
How long does the reflog keep entries?
Reachable entries are kept for 90 days and unreachable ones for 30 days by default, controlled by gc.reflogExpire and gc.reflogExpireUnreachable. That gives you a generous window, but the entries are local only — a fresh clone has an empty reflog.
Can I recover uncommitted changes lost to git reset --hard?
Only if they had been staged with git add at some point, in which case git fsck --lost-found will surface them as dangling blobs. Changes that were only ever edits on disk were never given to Git and cannot be recovered from the repository.
Does git reset --hard delete the commits permanently?
No. It moves the branch pointer and rewrites your working tree, but the commit objects stay in the database until garbage collection prunes unreachable objects — typically after 30 days for reflog-expired entries. Until then the reflog can take you back.
What does HEAD@{1} mean?
It's reflog notation for 'where HEAD pointed one move ago'. HEAD@{2} is two moves ago, and so on. It's convenient, but the numbering shifts with every command you run, so copy the actual commit hash for anything important.
Related rescue guides
I deleted a Git branch — how do I get it back?
Deleting a branch removes a pointer, not the commits. Find the branch's last commit hash in the reflog and recreate the branch at that hash with git branch <name> <hash>. If the branch was pushed, the copy on the server may still exist and can simply be fetched back.
Read the fix →Usually recoverableMy rebase went wrong and my commits are gone — how do I get them back?
The pre-rebase commits are still in the object database. git reflog shows the position from before the rebase started, and ORIG_HEAD is a shortcut to it — git reset --hard ORIG_HEAD usually restores everything in one command.
Read the fix →Sometimes recoverableI permanently deleted a file that was never committed — can I get it back?
It comes down to one question: was the file ever staged with git add? If it was, its contents are sitting in Git's object database as a dangling blob and git fsck will find it. If it was never staged and never committed, Git genuinely never saw the file and cannot help — but your editor's local history almost certainly can.
Read the fix →Usually recoverableSomeone force-pushed and my commits are gone — how do I get them back?
Your local clone still has the commits, and your reflog records where the branch pointed before the force-push overwrote it. Find that hash with git reflog, recover it to a branch, and push it back. If your local copy is already clean, a teammate's clone or the server's reflog may still have it.
Read the fix →