How to undo a Git commit: reset, revert, and amend
The right command for each situation: fix the last commit, undo local commits, revert something that's already on the remote, and recover what seemed lost.
Committed the wrong file, made a typo in the message, or pushed something to main that shouldn't be there? Everyone has been there. Git has several ways to undo a commit, and picking the right one comes down to one question: has this commit already been pushed to the remote?
Quick summary
- Fix the last commit, not yet pushed:
git commit --amend. - Undo local commits, not yet pushed:
git reset. - Undo a commit that's already on the remote:
git revert. - Recover something that seemed lost:
git reflog.
Fix the last commit with amend
If the problem is just the message, or you forgot to include a file, --amend replaces the last commit with a corrected version:
# just change the message
git commit --amend -m "Fix email validation"
# add a forgotten file and keep the message
git add src/validation.ts
git commit --amend --no-edit--amend creates a new commit in place of the old one. That's why you should only use it on commits you haven't pushed yet. If you already pushed, you'll need git push --force-with-lease, and that causes trouble for anyone who already pulled the old commit.
Undo local commits with reset
git reset moves the branch back to an earlier commit. The modes differ in what happens to the changes from the undone commits:
git reset --soft HEAD~1 # undo the commit and keep the changes staged
git reset --mixed HEAD~1 # undo the commit and keep the changes unstaged (default)
git reset --hard HEAD~1 # undo the commit and delete the changes--softis useful for squashing several commits into one: undo the last few and commit again.--mixedis useful for redoing the commit with a better choice of files.--hardthrows away your work. Use it carefully and only when you're sure.
HEAD~1 means one commit before the current one. HEAD~3 goes back three commits. You can also use the hash: git reset --soft a1b2c3d.
Undo a pushed commit with revert
When the commit is already on the remote and other people may have pulled it, don't rewrite history. Use git revert, which creates a new commit that does exactly the opposite:
git revert a1b2c3d
git pushThe history still shows the original commit and, after it, the commit that undid it. Nobody on the team needs to do anything special.
To revert a merge commit, tell Git which side to keep with -m 1, which is usually the main branch:
git revert -m 1 <merge-hash>Recover what seemed lost with reflog
Ran reset --hard and regretted it? Git keeps every position HEAD has been at for a while. git reflog shows that list:
git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# f4e5d6c HEAD@{1}: commit: Add CSV export
git reset --hard f4e5d6cThis works for commits that existed in your local repository. Changes that were never committed and got wiped with --hard don't show up in the reflog.
Undo changes that aren't committed yet
- Discard changes in a file:
git restore src/app.ts. - Unstage a file without losing the change:
git restore --staged src/app.ts. - Set everything aside for later:
git stash, and bring it back withgit stash pop.
Undoing commits in GitMuninn
In GitMuninn, the graph shows exactly where each commit is and which branches it's already in. You can see whether a commit has gone to the remote before you choose between reset and revert, and each file's history is one click away.

