Course contents

Undo the last commit, keep changes staged

Sign in to run this lab and save your progress

Learn

Sometimes you commit and immediately regret it: wrong message, wrong scope, wrong grouping of files. You don't want to lose the work, you just want the commit itself to go away so you can recompose it. That's what soft reset is for.

The three flavours of reset

git reset has three modes, and picking the right one is the whole game. The mode determines what happens to your files:

Mode HEAD Staging area Working tree
--soft moves back untouched untouched
--mixed (default) moves back reset to match HEAD untouched
--hard moves back reset to match HEAD reset to match HEAD

In every mode, the branch pointer moves backwards to the commit you specified. The differences are in what happens to your files.

  • --soft keeps everything exactly as it is; only the commit history changes. All the file changes from the un-done commits are still staged, ready for a fresh commit.
  • --mixed (the default when you don't specify) moves the changes from staged to unstaged. Files are still modified on disk, but not currently staged.
  • --hard throws everything out. Files revert to the state at the target commit. Destructive.

The soft reset recipe

To "undo" your most recent commit while keeping the changes ready to re-commit:

git reset --soft HEAD~1

HEAD~1 means "one commit before HEAD". So this moves the branch pointer back by one commit, keeping the staging area and working tree untouched. Run git status and you'll see all the files from your undone commit still staged, exactly as they were when you committed them.

From here you can:

  • Commit again with a better message: git commit -m "New message".
  • Unstage a file to leave it for a separate commit: git restore --staged <file>.
  • Add more files and commit them all together.
  • Change your mind and re-run the same commit: git commit -m "...".

The undone commit's changes are preserved in staging. You have full control over what happens next.

Going back further

HEAD~1 is one commit back. HEAD~3 is three commits back. So:

git reset --soft HEAD~3

Moves the branch pointer back three commits. All three commits' file changes accumulate in the staging area. This is the "squash" recipe from the rewriting module, in a slightly different shape.

What about reset vs amend

Both git commit --amend and git reset --soft HEAD~1 let you modify the most recent commit. When do you use which?

  • --amend when you want to keep most of the commit and just tweak one thing (the message, add a forgotten file). Simpler.
  • --soft reset when you want to fully rebuild the commit from scratch, or when you're going back more than one commit. More flexible.

Both operations produce a new commit with a new SHA. Both are subject to the "don't rewrite pushed commits" rule.

The reset warning applies here too

Even though soft reset preserves your files, it still rewrites commit history. The commits before the reset had one set of SHAs; after the reset, those commits are unreachable from your branch. If you've pushed them, anyone else has the old versions and you're now diverging in a hard-to-reconcile way.

Local reset before push: fine, common. Reset commits others have: never.

Your task

You committed too early. The repository has two commits: Initial (added a.txt) and Add b (added b.txt). You want to undo the most recent commit but keep b.txt staged so you can fix things up — change the message, split into smaller commits, whatever — without losing the work. After this, HEAD should be at Initial and b.txt should still be in the staging area.