revert is the safe undo for shared history
Reset rewrites history. Revert extends history with an inverse commit. git revert <hash> creates a new commit whose changes are exactly the opposite of the target commit — same files modified, in reverse direction. The history record stays intact: the original commit is still there, and a new revert commit on top says "we undid that one." This is the only safe undo for commits that have been pushed and that others have based work on.
The semantics are clean. git revert HEAD creates a revert of the most recent commit. git revert abc1234 reverts a specific older commit, even if dozens of commits sit between it and HEAD. If the revert touches lines that have moved or been further modified, you get conflicts — same resolution loop as a merge: edit, git add, git revert --continue. git revert --no-edit skips the editor and uses Git's default message.
For a range of commits, git revert OLDEST..NEWEST creates one revert commit per source commit, in reverse order. Useful when you need to undo a sequence of related changes. --no-commit stages the revert without committing, letting you bundle multiple reverts into a single commit if that reads better in history.
The special case: reverting a merge commit. Merge commits have two parents, so Git needs to know which side is the "mainline" you want to keep. git revert -m 1 <merge-hash> reverts the merge by undoing the changes that came in from parent 2 (the merged-in branch), keeping the parent-1 line of history intact. This is the right move when a merged feature turns out to be broken and you cannot afford a full reset.