devkult_
tools29converters34
home/blog/git-undo-last-commit
git

How to Undo the Last Git Commit: Reset, Revert or Amend

Which command you need depends on two questions: have you pushed the commit, and do you want to keep the changes?

Situation Command
Not pushed — undo the commit, keep the changes staged git reset --soft HEAD~1
Not pushed — undo the commit, keep the changes unstaged git reset HEAD~1
Not pushed — throw the commit and its changes away git reset --hard HEAD~1
Fix the last commit's message or add a forgotten file git commit --amend
Already pushed to a shared branch git revert HEAD

HEAD~1 means "the commit before the current one". Use HEAD~3 to go back three commits.

Undo a commit but keep the work

git reset --soft HEAD~1

The commit disappears and its changes are left staged, ready to commit again — useful when you committed too early or want to split the work differently.

git reset HEAD~1

The default (--mixed) does the same but leaves the changes unstaged in your working directory, so you can choose again what goes into each commit.

Throw the commit away completely

git reset --hard HEAD~1

This deletes the commit and discards its changes from your files. Uncommitted work in your working directory is discarded too, so check git status first. (The commit itself is still recoverable for a while — see reflog below.)

Fix the last commit instead

To change the message:

git commit --amend -m "Better message"

To add a file you forgot:

git add forgotten-file.js
git commit --amend --no-edit

Amending replaces the commit with a new one. That's fine locally, but if you've already pushed it, the next push needs force (see below).

Undo a commit that's already pushed

On a branch other people use, don't rewrite history. Create a new commit that reverses the old one:

git revert HEAD
git push

git revert works on any commit, not just the last: git revert a1b2c3d. To revert a merge commit, tell Git which parent to keep — usually the first, the branch you merged into:

git revert -m 1 <merge-commit>

Pushed, but only to your own branch

If nobody else has pulled the branch — say, your own feature branch — you can rewrite it and force-push:

git reset --hard HEAD~1
git push --force-with-lease

--force-with-lease refuses to push if the remote has commits you haven't seen, so you can't silently wipe out someone else's work. Prefer it to plain --force.

Recover from a reset you regret

Git keeps a log of every position HEAD has been at, including commits you reset away:

git reflog
e4f5a6b HEAD@{0}: reset: moving to HEAD~1
9c8d7e1 HEAD@{1}: commit: Add search endpoint

Jump back to the commit before the reset:

git reset --hard HEAD@{1}

The same trick undoes an amend: git reset --soft HEAD@{1} puts back the original commit and leaves the amended changes staged. Reflog entries are kept for 90 days by default, and only in your local repository.

A few related undos

git restore --staged file.js    # unstage a file, keep the edits
git restore file.js             # discard uncommitted edits to a file
git update-ref -d HEAD          # undo the very first commit in a repo

The last one is needed because the first commit has no parent, so HEAD~1 doesn't exist.

More from the blog