Skip to content
PC Moment
Programming

Git Undo Last Commit: Reset, Revert, Amend and How to Get It Back

Undo your last Git commit the right way: keep the changes, throw them away, or reverse a commit you already pushed, plus how to recover from a bad reset.

By PC MomentUpdated 7 min read

PC Moment title card for Git Undo Last Commit

You committed too early, wrote the wrong message, or committed something that shouldn’t be there at all. Git gives you several ways to undo the last commit, and the right one depends on two questions: do you want to keep the changes, and have you already pushed the commit?

The quick answer: if the commit is still only on your machine, git reset --soft HEAD~1 removes the commit and keeps everything staged. If you already pushed it, use git revert HEAD instead.

Pick the right command first

Use this table to choose before you type anything:

Your situationCommandWhat happens to your changes
Not pushed, want to recommit with editsgit reset --soft HEAD~1Kept and still staged
Not pushed, want to restage selectivelygit reset HEAD~1Kept in your files, unstaged
Not pushed, want the work gonegit reset --hard HEAD~1Discarded
Just need to fix the message or add a filegit commit --amendFolded into a replacement commit
Already pushed to a shared branchgit revert HEADReversed by a new commit

HEAD is the commit you’re on now, and HEAD~1 means “one commit before it.” So every reset command below moves your branch back by one commit. The only difference between the modes is what happens to your files and your staging area (the index).

Before you start, run git status and git log --oneline -5 so you can see what you’re about to change.

git status
git log --oneline -5

The first command shows uncommitted changes. The second lists your last five commits, newest first, so you can confirm the top one is the commit you want to undo.

How to undo the last commit and keep your changes

Option 1: git reset —soft (keep changes staged)

This is the gentlest undo. It removes the commit but leaves your working files and staging area exactly as they were at the moment you committed.

git reset --soft HEAD~1

The git documentation describes --soft as leaving “your working tree files and the index unchanged.” In practice, everything from the undone commit shows up as staged in git status, ready for you to edit and commit again.

A typical fix-up looks like this:

git reset --soft HEAD~1
git add forgotten-file.txt
git commit -c ORIG_HEAD

Between the reset and the new commit, edit your files and git add anything you forgot. git reset saves the old tip of your branch as ORIG_HEAD, and git commit -c ORIG_HEAD starts the new commit with the old commit message so you can edit it. Use -C ORIG_HEAD instead if you want to reuse the message as is.

Option 2: git reset —mixed (keep changes, unstaged)

Mixed mode is the default, so you don’t have to type --mixed:

git reset HEAD~1

Your files stay exactly as they are, but nothing is staged anymore. This is handy when the commit mixed two unrelated changes and you want to split it: stage one part with git add, commit it, then stage and commit the rest.

Option 3: git commit —amend (fix the last commit in place)

If you only need to change the commit message or add a forgotten file, you don’t have to undo anything. Amend the commit instead:

git add forgotten-file.txt
git commit --amend

This replaces the tip of the current branch with a new commit built from your current staging area, and it opens your editor with the old message as a starting point. To keep the message unchanged, add --no-edit:

git commit --amend --no-edit

If nothing new is staged, --amend only changes the message.

Important: Amending creates a brand-new commit that replaces the old one. The Pro Git book says to amend only commits that are still local and haven’t been pushed. If you already pushed, see the git revert section below, or read about git push —force-with-lease if you’re sure nobody else uses that branch.

How to undo the last commit and discard the changes

Important: git reset --hard throws away uncommitted work. It overwrites your tracked files with the version from the commit you reset to, and it may overwrite untracked files too. Run git status first and commit or stash anything you want to keep. Changes that were never committed cannot be recovered with the reflog.

When the last commit was a mistake from start to finish and you don’t want any of it:

git reset --hard HEAD~1

This moves your branch back one commit and makes your working folder match that commit exactly. Nothing is left staged.

To undo more than one commit, change the number. git reset --hard HEAD~3 drops the last three commits. The git manual adds a clear warning for this exact example: don’t do it if you have already given these commits to somebody else.

How to undo a commit you already pushed

Once a commit is on a shared branch, other people may have pulled it. Removing it with reset and force-pushing rewrites history under them. The safe option is git revert, which records a new commit that reverses the changes of the old one:

git revert HEAD

Git opens your editor with a message like Revert "your original message". Save and close it, then push as usual:

git push

Nothing in history is deleted. Anyone who already pulled the bad commit simply pulls the revert on top of it.

A few useful variations:

  • git revert --no-edit HEAD skips the editor and uses the default message.
  • git revert -n HEAD (or --no-commit) applies the reversal to your files and staging area without committing, so you can review or combine it before committing.
  • git revert needs a clean working tree. Commit or stash your local changes first.

Tip: The git docs sum up the split neatly. revert records new commits that reverse earlier ones; reset --hard throws away uncommitted changes. On a branch other people use, reach for revert.

If you’re working alone on a feature branch and really want the commit gone from the remote, you can reset locally and then force-push. Use git push --force-with-lease rather than plain --force, because it refuses to overwrite the remote if someone pushed in the meantime. Our guide to git push force with lease walks through it.

How to recover from a bad reset with git reflog

Reset the wrong commit, or used --hard when you meant --soft? As long as the work was committed, you can almost always get it back. Git keeps a reference log (“reflog”) of every place HEAD has pointed in your local repository.

  1. List recent positions of HEAD:

    git reflog

    You’ll see lines like these, newest first:

    5790906 HEAD@{0}: reset: moving to HEAD~1
    7777911 HEAD@{1}: commit: Add login form

    HEAD@{1} means “where HEAD was one move ago.” Here that’s the commit you just reset away.

  2. Move your branch back to that entry:

    git reset --hard "HEAD@{1}"

    Your branch now points at the lost commit again, and your files match it. The quotes stop PowerShell from misreading the curly braces; they work the same way in Bash and Git Bash.

    Important: This is another --hard reset, so any uncommitted changes you have right now will be overwritten. Commit or stash them first.

  3. Check the result with git log --oneline -5.

Reflog entries don’t last forever. By default, Git expires entries after 90 days, and entries for commits that are no longer reachable from any branch after 30 days (the gc.reflogExpire and gc.reflogExpireUnreachable settings). Recover sooner rather than later. The reflog is also local only: it lives in your clone and isn’t pushed anywhere.

Common errors when undoing a commit

fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree. You’re trying to undo the very first commit in the repository, so there is no HEAD~1. If that’s the case, it’s often simpler to fix the commit with git commit --amend.

fatal: not a git repository (or any of the parent directories): .git You’re running the command outside your project folder. See our fix for fatal: not a git repository.

Push rejected after a reset or amend After you rewrite a commit that was already pushed, a normal git push is rejected because your branch no longer contains the remote’s tip. Either switch to git revert, or, on a branch only you use, push with --force-with-lease. If the branch has never been pushed at all, see git push set upstream instead.

If it still doesn’t work

  • Run git status and read it carefully. It tells you which branch you’re on, whether you’re in the middle of a merge, rebase or revert, and what’s staged.
  • Run git log --oneline --graph -10 to see where your branch actually points.
  • If a revert stops with conflicts, fix the files Git lists, git add them, then run git revert --continue. To give up and return to where you started, run git revert --abort.
  • If you think you lost work, stop and check git reflog before running any more reset commands.
  • On a team repository with protected branches, you may not be allowed to force-push at all. Ask the repository admin, and use git revert in the meantime.

Looking for more Git and coding fixes? Browse the programming guides.

Frequently asked questions

How do I undo the last commit but keep my changes?

Run git reset --soft HEAD~1 to keep the changes staged, or git reset HEAD~1 (mixed mode, the default) to keep them in your files but unstaged. Neither option touches your working files.

How do I undo a commit I already pushed?

Use git revert HEAD. It creates a new commit that reverses the last one, so you can push it normally without rewriting history that other people may already have.

What is the difference between git reset and git revert?

git reset moves your branch back so the commit disappears from its history. git revert leaves history alone and adds a new commit that cancels out the old one, which is the safe choice for shared branches.

Can I get a commit back after git reset --hard?

Usually, yes, if it was committed. Run git reflog to find the commit's position, then git reset --hard to that entry, for example "HEAD@{1}". Uncommitted changes that --hard overwrote are not in the reflog.

Why does git reset HEAD~1 say ambiguous argument?

If the commit you want to undo is the very first commit in the repository, there is no HEAD~1 to go back to, so Git reports an unknown revision.

Related guides