Git & GitHub · 11 min · 120 XP

Undo local commits with reset

Undo commits you haven't pushed with reset, and know which of its modes deletes work.

git restore undoes edits you haven't committed. git reset goes a step further: it moves your branch back to an earlier commit, as if the later ones had never been made. HEAD~1 means one commit before where I am, and HEAD~3 means three.

Reset has three modes. They differ only in what happens to the changes from the commits you're undoing. With --soft they stay staged, ready to commit again. With --mixed, the default, they stay in your files but unstaged. With --hard they're thrown away, along with any uncommitted edits you had.

bash
git reset --soft HEAD~1   # undo the commit, keep its changes staged
git reset HEAD~1          # undo the commit, keep its changes unstaged
git reset --hard HEAD~1   # undo the commit and delete its changes

reset rewrites history, so the rule from Pull requests and review applies: use it only on commits you haven't pushed, and git revert the ones you have. --hard also deletes uncommitted edits for good, so run git status before you use it. (Commits it removes can still be recovered, as the reflog lesson shows.)

Scenario: three commits that should have been one
$ git log --oneline
d4e5f6a (HEAD -> feature/coupons) fix typo
c3d4e5f wip 2
b2c3d4e wip
a1b2c3d (origin/main, main) Fix rounding in cart total
Scenario: two files edited, nothing committed
$ git status --short
 M src/cart.js
 M src/checkout.js
$ git log --oneline -1
a1b2c3d (HEAD -> main, origin/main) Fix rounding in cart total

Try it on your machine: make three small commits on a practice branch. Run git reset --soft HEAD~3 and check git status: everything is staged. Commit it as one. Then make a throwaway commit and try git reset HEAD~1 and see the change come back unstaged.

Loading your workspace…