Git Revert

Git revert undoes the changes from a commit by creating a brand-new commit, making it the safest way to back out changes on branches other people share.

What Reverting Actually Does

When you run git revert, Git looks at the changes introduced by a target commit and applies the exact opposite of those changes as a new commit on top of your current history. The original commit is never removed, edited, or hidden — it stays in the log forever, and a second commit sits above it recording the undo. This matters because history that has already been pushed and pulled by teammates should never be rewritten; deleting or altering a commit that others have based work on will cause painful conflicts the next time they sync. Revert sidesteps that entirely by only ever adding new commits.

You can revert any commit, not just the most recent one, and you can revert a commit that itself was a merge, a feature addition, a bug fix — anything. Git figures out the inverse diff and tries to apply it cleanly to your working tree.

Reverting the Last Commit

The simplest case is undoing whatever you just committed. Git opens an editor with a default message like 'Revert "original commit subject"' so you can confirm or adjust it before the new commit is created.

Revert the most recent commit

$ git log --oneline -3
d4a9f21 (HEAD -> main) Add experimental pricing banner
7c1e88a Fix footer alignment on mobile
a93bb02 Update dependencies

$ git revert HEAD
[main 5f2c9d0] Revert "Add experimental pricing banner"
 1 file changed, 12 deletions(-)

$ git log --oneline -3
5f2c9d0 (HEAD -> main) Revert "Add experimental pricing banner"
d4a9f21 Add experimental pricing banner
7c1e88a Fix footer alignment on mobile

Reverting a Commit Further Back

You are not limited to HEAD. Pass any commit hash, and Git will attempt to invert that specific commit's changes even if newer commits have since touched the same file. If later commits depend on the change you're undoing, you'll likely hit a conflict that needs manual resolution.

Revert an older commit by hash

$ git revert 7c1e88a
Auto-merging src/styles/footer.css
[main 9b3d410] Revert "Fix footer alignment on mobile"
 1 file changed, 3 insertions(+), 3 deletions(-)

Reverting a Range or a Merge Commit

Reverting several commits at once is possible with a range, and Git will create one revert commit per entry unless you pass --no-commit to stage them all together. Merge commits need special handling: because a merge has two parents, you must tell Git which parent's history to treat as 'mainline' using the -m flag, almost always -m 1 for the branch you merged into.

Revert a merge commit

$ git log --oneline --merges -1
e71a209 (HEAD -> main) Merge branch 'feature/checkout-v2'

$ git revert -m 1 e71a209
[main a0f5c31] Revert "Merge branch 'feature/checkout-v2'"
 8 files changed, 210 deletions(-), 4 insertions(+)
  • git revert HEAD — undo the most recent commit
  • git revert <hash> — undo a specific commit anywhere in history
  • git revert <hash1>..<hash2> — undo a range of commits, one revert commit each
  • git revert -n <hash> — revert but stage changes without committing, for batching
  • git revert -m 1 <merge-hash> — revert a merge commit against its first parent
  • git revert --abort — bail out of a revert that hit conflicts
Note: Revert conflicts look and resolve exactly like merge conflicts: Git marks the files, you edit out the conflict markers, git add the result, then git revert --continue.

Revert vs Reset

Aspectgit revertgit reset
HistoryAdds a new commit; old commit staysMoves the branch pointer; commits can be dropped
Safe for shared branchesYesNo, unless only local and unpushed
Undo visibilityExplicit in log — everyone sees the undoSilent — history looks like it never happened
Typical useUndoing a change already pushed/deployedCleaning up local, unpublished commits
Working directory effectApplies inverse patch, may conflictCan discard changes instantly with --hard
Note: If you're tempted to use reset --hard on a commit that's already been pushed and pulled by someone else, stop and use revert instead. Rewriting shared history forces everyone else to reconcile diverged branches manually.

A good habit is to treat revert as your default undo tool for anything already shared, and reserve reset for commits that exist only on your machine. Reaching for revert first also gives you a paper trail: a code reviewer or teammate can see exactly what was undone and when, which is often valuable during incident response.

Exercise: Git Revert

What does `git revert` do differently from `git reset`?