Your coding assistant just made five commits, and one of them broke everything. Or maybe that was you at 2:00 AM. Either way, by the end of this post you’ll know how to undo any commit in Git without losing your work.
Undoing a commit can sound scary, but it comes down to one question and three commands. The question is: have you pushed the commit yet? I’ll walk you through reset, revert, and the safety net that gets you unstuck when you thought you lost everything.
The mental model
A commit is a snapshot of your project at a moment in time. HEAD is just a pointer to the snapshot you are currently on. When people say “undo a commit,” they usually mean one of three things:
- They want to undo a commit but keep the code.
- They want the commit and the changes gone entirely.
- The changes are already shared with the team, but they need to reverse it safely.
Those are three different jobs, and using the wrong tool can lead to conflicts and messy history. So before you touch anything, ask: Have I pushed the commit I want to undo yet?
Still local? Use reset
If the changes are still only on your machine, use git reset. Reset moves HEAD back, and it has three flavors that decide what happens to your code.
Soft — undo the commit, keep everything staged
You committed too early, but the code is good. You want to uncommit and keep everything staged, ready to recommit:
|
The commit is gone, but the work isn’t. HEAD~1 means one commit back. Change the 1 to undo more commits at once.
Default (mixed) — undo the commit, unstage the changes
Same idea, but your changes go back to unstaged so you can edit before you re-commit:
|
Files are untouched. You only undid the commit and the staging.
Hard — throw the commit and the changes away
This is the dangerous one. You want the commit and the changes gone:
|
Only reach for --hard when you are sure, because it is the one people regret the most. Even then, you can often still recover — more on that below.
Summary
| Flavor | Commit | Staging | Working tree |
|---|---|---|---|
--soft | removed | kept | kept |
| (default) | removed | unstaged | kept |
--hard | removed | cleared | discarded |
Already pushed? Use revert
If you already pushed the commit, or it is on a branch your teammates pulled, don’t reset. Rewriting history that other people already have makes a mess for everyone. Use git revert instead.
Revert does not delete anything. It creates a brand new commit that is exactly the opposite of the one you want to undo. History stays intact, everyone stays in sync, and the bad change is gone.
|
You can revert any commit, not just the last one. Git writes the inverse operations and opens a commit message for you. If you added a file in the bad commit, the revert removes that file. The history is there, but it is undone.
Rule of thumb: if you already pushed it → revert. If things are still local → reset.
The safety net: reflog
Say you ran a hard reset by mistake and it looks like your commit and your work vanished. Almost certainly it is still there. Git keeps a log of everywhere HEAD has been, called the reflog.
|
You see a list of every recent move, each with its own hash. Find the state you want to go back to, copy the hash, and reset to it:
|
You are back like it never happened. Before you panic about lost commits, check the reflog. Nine times out of ten, the work is sitting right there.
The one thing reflog cannot save you from is deleting the .git folder itself — so don’t do that.
I wrote a deeper dive on this: Recovering lost commits with git reflog.
Bonus: amend
Sometimes you don’t want to undo a commit — you just want to fix it (wrong message, or you forgot a file).
|
|
|
Remember: amend also rewrites history, so the push-or-not-push rule still applies.
Cheat sheet
- Have I pushed the commit yet?
- No →
reset--softto keep it staged- default to keep it unstaged
--hardto throw everything away
- Yes →
revert(safe reverse with a new commit) - Looks lost? →
git reflog, thengit reset --hard <hash> - Just need a small fix on the last local commit? →
git commit --amend
Those are most of the commands you ever need to fix or undo a commit in Git.
If this made Git feel less scary, the next deep-dive is about the git commands you actually use every day. In the meantime, tell me in the comments: what’s the worst Git mistake you ever had to undo?