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.

CommandEffectUse when
git revert <commit>Creates a new commit that applies the exact opposite of an old oneThe commit is already pushed/shared with others
git reset --soft <commit>Moves your branch pointer back, keeps the undone changes stagedLocal 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 tooLocal 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 --hard permanently discards uncommitted work in your working directory and rewrites your branch's history. Never reset --hard a 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 for revert instead.
Tip: If you're ever unsure exactly what a reset would discard, run git status and git diff first to see your current uncommitted changes, and consider git stash as a safer alternative if you just want them out of the way rather than gone forever.