Undoing: reset vs revert
Two Ways to Undo
Scenario: You committed something broken. Do you erase it from history, or add a new commit that cancels it out? The answer depends entirely on whether you've already pushed it and whether anyone else might have it - and getting this wrong is one of the most common ways people lose work or wreck a shared branch.
Before the table, one piece of vocabulary you'll need constantly from here on: HEAD is Git's name for "the commit you currently have checked out" - think of it as a pointer to where you are right now in the history. HEAD~1 means "one commit before HEAD", HEAD~2 means "two before", and so on.
| Command | Effect | Use when |
|---|---|---|
git revert <commit> | Creates a new commit that applies the exact opposite of an old one | The commit is already pushed/shared with others |
git reset --soft <commit> | Moves your branch pointer back, keeps the undone changes staged | Local only, and you want to redo/amend the commit |
git reset --mixed <commit> | Moves back, keeps the changes but unstages them (this is the default if you omit the flag) | Local only, want to re-stage selectively |
git reset --hard <commit> | Moves back and permanently discards those changes from your working files too | Local only, and you genuinely want the work gone |
$ git reset --soft HEAD~1 # undo last commit, keep the changes staged
$ git revert HEAD # safely undo a pushed commit with a new commit
The key mental model: reset rewrites history (it moves where your branch pointer says the history ends), while revert adds to history (it leaves the old commit exactly where it was, and adds a brand-new one on top that cancels it out). That's why revert is safe to use on a branch other people already have a copy of - their history and yours never disagree - while reset changes what your branch pointer even means, which is fine locally but breaks things for anyone who already pulled the commit you erased.
Danger:git reset --hardpermanently discards uncommitted work in your working directory and rewrites your branch's history. Neverreset --harda branch you've already pushed and that others use - their local copies still have the "old" history, and things get confusing and messy fast when they try to sync. On shared branches, always reach forrevertinstead.
Tip: If you're ever unsure exactly what a reset would discard, rungit statusandgit difffirst to see your current uncommitted changes, and considergit stashas a safer alternative if you just want them out of the way rather than gone forever.