How to undo the last commit in Git

Four cases, four commands. Find your sentence below and copy the command under it. Rule zero: pushed already? Use revert. Everything else assumes the commit is still local.

🎙️ Published & recorded: ·

Keep the changes, or throw them away

If the commit is local, decide what should happen to its files. Soft reset removes only the commit and leaves every change staged, so it is the right default when you plan to recommit. Hard reset removes the commit and makes your working files match the previous snapshot. Do not use hard reset merely because the word “undo” sounds decisive.

# "Undo the commit, KEEP my changes" — most common:
git reset --soft HEAD~1

# "Undo the commit AND throw away the changes":
git reset --hard HEAD~1

# Last N commits, with all changes staged as one pile:
git reset --soft HEAD~3
Real error: the commit has no parentfatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree.

Run git log --oneline. If it shows only one commit, there is no earlier snapshot for reset to target. Keep the files, create a new orphan branch if you truly need fresh history, or amend that first commit instead. Adding random tildes cannot produce a parent that does not exist.

Fix the message or add a forgotten file

Amend replaces the latest commit with a corrected one. Use it for a typo in the message or a file you forgot to stage. The commit hash changes, so amend is clean while the commit is still yours and still local. If teammates may already have the old hash, make a new commit instead.

# The content is right; only the message is wrong:
git commit --amend -m "the message I meant to write"

# Add a forgotten file without changing the message:
git add forgotten.py
git commit --amend --no-edit
Real error: nothing exists to amendfatal: You have nothing to amend.

Check git log --oneline. You are either in a repository with no commits, or on an unborn branch. Stage the files and create the first normal commit; amend only works when HEAD already points to a commit.

Already pushed: revert, do not rewrite

Revert reads an existing commit and creates a new commit with the opposite change. That keeps the public history intact, which means a teammate who already pulled does not have to repair their branch. On a shared branch, I would rather explain an ugly revert commit than explain why somebody’s work vanished after a force-push.

git revert HEAD
# creates a new commit that cancels the latest one; then push it

git revert abc1234
# same operation for an older commit by hash
If revert stops on a conflicterror: could not revert abc1234... Remove broken validation
hint: after resolving the conflicts, mark the corrected paths with 'git add <paths>'

Run git status, open each unmerged file, keep the version that represents the desired post-revert code, delete the conflict markers, then run git add for each file and git revert --continue. To abandon the attempt and restore the pre-revert state, run git revert --abort.

Recover after reset --hard with reflog

A hard reset moves the branch label, but Git usually keeps the old commit object. Reflog records where HEAD used to point. Read the entries, identify the commit before the reset, inspect it if necessary, and only then move back. Do not assume HEAD at one is always the right entry; another command may have added a newer reflog record.

git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# f4e5d6c HEAD@{1}: commit: the one you want back

git show f4e5d6c             # inspect before moving anything
git reset --hard f4e5d6c     # restore that exact commit
# equivalent here: git reset --hard HEAD@{1}
Cheat tableKeep changes: reset --soft HEAD~1 · discard: reset --hard HEAD~1 · fix latest commit: --amend · already pushed: revert HEAD · recover: reflog.
This is one page of our Git series. For the three-tree mental model and the full audio guide, read Git in 10 Minutes →

Tell me what missed

A correction is more useful than a compliment. This goes straight to the person who writes SwiftGrasp.

Was this page useful?
0/1000

Please do not include passwords, private keys, or personal information.