git revert
git revert is the safe undo for shared history. Instead of rewriting the past, it appends a new commit whose changes are the exact inverse of an older commit. The bad commit stays in history; you just added a fix on top of it. That makes revert the only undo command you can use without panic on a branch other people have pulled.
How revert differs from reset
Reset rewinds; revert appends
Before: A ─ B ─ C ◀── main
git reset --hard B: A ─ B ◀── main (C is now unreachable)
git revert C: A ─ B ─ C ─ C' ◀── main
▲
"Revert C" — applies the inverse of C
so the working state matches B again.The basic revert
Undo a commit
# Revert a specific commit by SHA git revert 9c1a2b3 # Revert the most recent commit git revert HEAD # Revert two commits ago git revert HEAD~2 # Git opens the editor with a default message like: # Revert "Add broken feature" # This reverts commit 9c1a2b3...
Multiple commits
Revert several at once
# Multiple specific commits — creates one revert commit per source commit git revert A B C # A range — reverts everything in the range, newest first git revert OLD..NEW # Note: the range is exclusive of OLD and inclusive of NEW
--no-commit: combine reverts into one
Pass --no-commit (or -n) to stage the inverse changes without committing. You can chain several reverts and then make a single commit at the end.
One commit for many reverts
git revert --no-commit A git revert --no-commit B git revert --no-commit C git commit -m "Roll back broken feature (A, B, C)"
Reverting a merge commit
Roll back a merge
# Find the merge commit git log --oneline --merges # Revert it, keeping main (parent 1) as the mainline git revert -m 1 <merge-sha> # This produces a commit that undoes everything the merge brought in.
Conflicts during revert
If the changes in the target commit overlap with later commits, Git will pause with a conflict, just like a merge. You resolve the conflict manually, stage the result, and continue.
The revert conflict loop
git revert 9c1a2b3 # CONFLICT (content): Merge conflict in src/util.js # error: could not revert 9c1a2b3... # Fix the conflict markers in the affected files vim src/util.js git add src/util.js git revert --continue # finish creating the revert commit # or git revert --skip # drop this revert, continue with the next # or git revert --abort # undo the whole revert operation
revert vs reset (when to pick which)
Situation | Pick |
|---|---|
Already pushed, others have pulled |
|
Local commits only, never shared |
|
Need to keep the bad commit visible in history |
|
Want history to look like the mistake never happened |
|
Reverting one bad change inside a long-merged feature |
|
When revert is not the right tool
You want to throw away your own unpushed commits — use
git resetand avoid bloating history with revert commits.You need to remove a leaked secret from history — revert leaves the secret in the old commit. Use
git filter-repo(and rotate the secret).You are reverting a revert — possible, but think hard. The “revert of the revert” often surprises teammates. Prefer cherry-picking the original work onto a fresh commit.