HOWTO · Git

How to Undo the Last Git Commit in a Local Repository

Choose how git reset handles the changes when undoing a local Git commit.

On this page

To undo a local commit, use git reset with the mode that matches what you want to do with its tracked changes: keep them staged, keep them unstaged, or discard them. Reset moves the current branch to an earlier commit. If the commit has already been shared, prefer git revert to preserve shared history.

Choose the reset mode

A commit records a snapshot, while the index holds the next snapshot to commit and the working tree contains your checked-out files. git reset moves the current branch tip to a chosen target. Its mode determines whether the index and working tree are also changed:

  • --soft moves the branch tip and leaves both the index and working tree as they were.
  • --mixed moves the branch tip and resets the index to the target, while leaving working-tree files in place. This is the default mode.
  • --hard moves the branch tip and resets both the index and tracked working-tree files to the target. It can discard tracked work.

Suppose history is A — B — C, with C checked out. Resetting to HEAD~1 moves the branch to B; the mode determines what happens to the changes introduced by C.

Undo the latest commit and keep changes staged

Use --soft when you want to remove the commit but keep its changes in the index, ready to commit again or edit before recommitting:

The command is git reset --soft HEAD~1.

Afterward, HEAD points to the previous commit, and the changes from the removed commit remain staged. Review them with git diff --cached before creating a replacement commit.

Undo the latest commit and keep changes unstaged

Use --mixed to remove the commit and leave its tracked changes in the working tree, but out of the index:

The command is git reset --mixed HEAD~1.

The files remain tracked; their differences from the new HEAD appear as unstaged modifications in git status. Since --mixed is the default, git reset HEAD~1 has the same effect. This is useful when you want to review or selectively stage the changes again.

Undo the latest commit and discard tracked changes

Use --hard only when you intend to discard the committed changes from the index and working tree. It resets tracked files to match the target commit, and any uncommitted changes to those tracked files can also be lost. Ordinary untracked files are generally left alone, but untracked files or directories that obstruct writing tracked paths from the target can be deleted. Check git status and preserve anything you may need before running the command.

The command is git reset --hard HEAD~1.

Choose a commit target and verify the result

HEAD~1 means the first parent of the current commit; HEAD~2 means two commits back. Choose the target carefully because reset moves the current branch there. Use git log --oneline --graph -5 to inspect recent history.

Then reset to the intended target, for example git reset --mixed HEAD~2. Verify the branch and file state with git log --oneline -3 and git status.

Run this example:

#!/usr/bin/env bash
set -eu
repo=$(mktemp -d)
trap 'rm -rf "$repo"' EXIT
cd "$repo"
git init -q
git config user.name Example
git config user.email example@example.com
printf 'first\n' > note.txt
git add note.txt
git commit -qm 'Add note'
printf 'second\n' >> note.txt
git commit -qam 'Extend note'
git reset --mixed HEAD~1 >/dev/null
git status --short
 M note.txt

The script creates a temporary repository, makes two commits, resets to the earlier commit with the latest change left unstaged, and prints the status. Its cleanup trap removes the temporary repository when the script exits.

If the commit is already shared

Resetting a commit that others have fetched rewrites the branch history. If you push the reset branch, collaborators may need to reconcile their copies, and a normal push may be rejected. For a commit already published to a shared branch, git revert <commit> creates a new commit that reverses the earlier change without removing it from history. Coordinate with collaborators before rewriting a shared branch.