GitMuninnGitMuninn
← Back to the blog

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
  • --soft is useful for squashing several commits into one: undo the last few and commit again.
  • --mixed is useful for redoing the commit with a better choice of files.
  • --hard throws 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 push

The 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 f4e5d6c

This 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 with git 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.

See your branches in GitMuninn.

Join the launch list and get 50% off Pro and Business for 12 months.

Plan you are interested in

For macOS, Windows, and Linux. No spam, leave anytime.