What Does git revert Do?
A thorough, zero-prior-knowledge walkthrough of Git's safest way to undo a change — what it does under the hood, how it differs from other "undo" commands, and how to use it with confidence on shared history.
Imagine you’re editing a shared, published encyclopedia. A previous edit you made turns out to be wrong, but the encyclopedia has already been printed and distributed to thousands of readers — you can’t simply tear out that page and pretend it never existed. What you can do is publish a new correction that says “the previous edit was wrong, here is the fix,” while keeping the full, honest record of what happened. That is exactly the philosophy behind git revert: instead of erasing history, it adds new history that cancels out an earlier change. In this guide, we’ll build this idea up completely from zero — what problem it solves, exactly what happens internally when you run it, how it compares to Git’s other undo tools, and how to use it safely on both personal and shared branches.
1Core Concepts: What Revert Actually Is
What it is: git revert is a Git command that undoes the changes introduced by a specific past commit, by creating a brand-new commit that applies the exact opposite of those changes. The original commit is never deleted, hidden, or rewritten — it stays exactly where it was in the project’s history, permanently visible.
Why it exists: Sometimes a change that was committed and shared with others turns out to be wrong, buggy, or simply unwanted — but by the time anyone notices, other people may have already built further work on top of it, or the change may already be running in production. Deleting that commit from history would be dangerous and confusing for everyone who already has a copy of it. git revert exists to undo the effect of the change while leaving the historical record completely intact and honest.
Where it’s used: git revert is the standard tool for undoing changes that have already been shared with others — pushed to a shared branch, merged into main, or deployed. It’s especially common as an emergency response when a bad change reaches production and needs to be undone quickly and safely.
Think of a company’s official meeting minutes. If someone realizes minute #14 recorded an incorrect decision, nobody rips page 14 out of the minutes book — instead, minute #27 is added later, stating “correction: the decision recorded in minute #14 was reversed.” Anyone reading the full minutes later sees both the original mistake and the correction, in order, with nothing hidden. git revert works the same way: it adds a new, clearly-labeled correcting entry rather than tampering with the original record.
Practical example: A team at an e-commerce company merges a change that updates how shipping costs are calculated. An hour after deployment, customers start reporting incorrect shipping charges. Instead of scrambling to figure out a fix under pressure, an engineer runs git revert on the problematic commit, instantly restoring the previous, working shipping-cost logic, while the team investigates the actual bug calmly, without time pressure.
2The Problem & Motivation Behind Revert
In the earliest, simplest model of version control, “undoing” a change meant literally deleting or rewriting the record of it — much like using correction fluid on a paper document. This works fine as long as only one person has ever seen that document. But software is almost never that simple: the moment a commit is pushed to a shared repository, other people may have already downloaded it, built new work on top of it, or even deployed it to run in production for real users.
If you tried to simply erase that commit from shared history at that point, you would create a serious mismatch: your copy of history would say the change never happened, while everyone else’s copy — and anyone who already deployed it — would still show it. Reconciling those two different versions of “what happened” is difficult and error-prone, and can silently reintroduce bugs when histories are merged back together.
git revert solves this by never touching the past at all. It only ever adds a new commit to the front of history. Because nothing already shared is ever changed or removed, there is no mismatch to reconcile — everyone’s history stays compatible, and everyone simply receives the new correcting commit the normal way, the same as any other change.
The core problem revert solves: how do you safely undo a change that other people, or other systems, may already depend on, without rewriting a shared, already-distributed history? Revert answers this by treating “undoing” as just another ordinary, forward-moving change — not a rewrite of the past.
3How Git Commits Work (The Foundation Revert Builds On)
A commit in Git is a saved snapshot of your entire project at one point in time, along with a message describing what changed and why. Each commit also stores a reference to the commit that came directly before it — this is what forms the connected chain we call “history.” Crucially, Git doesn’t usually store a change as “add this, remove that” in the commit itself — it stores full snapshots, but it can efficiently compute the difference (called a “diff”) between any two snapshots whenever needed.
When people talk about “what a commit changed,” they really mean the diff between that commit’s snapshot and its parent commit’s snapshot — the set of lines added, removed, or modified to get from one state to the next. This diff is exactly what git revert needs to compute its opposite.
per ordinary commit
to compute a diff
a project’s history can hold
This snapshot-and-diff relationship is the foundation that makes revert possible: because Git can always calculate exactly what a given commit changed relative to its parent, it can also calculate — and apply — the exact opposite of that change.
4Internal Working: What Happens When You Run git revert
flowchart LR
A["You run: git revert commit-X"] --> B["Git computes the diff introduced by commit-X"]
B --> C["Git computes the inverse of that diff"]
C --> D["Git applies the inverse diff to your current files"]
D --> E{"Applies cleanly?"}
E -->|Yes| F["Git creates a new commit with the inverse changes"]
E -->|No, conflict| G["You resolve the conflict manually, then finish the revert"]
G --> F
Step by step, in plain language: first, you tell Git which commit you want to undo the effect of. Second, Git looks at that commit and its parent, and computes exactly what changed between them — the diff. Third, Git calculates the mathematical inverse of that diff: everywhere the original commit added a line, the inverse removes it; everywhere it removed a line, the inverse adds it back; everywhere it modified a line, the inverse changes it back to the original wording. Fourth, Git attempts to apply that inverse diff on top of your current files. Fifth, if your files haven’t changed in a conflicting way since that commit, this applies cleanly and Git automatically creates a brand-new commit containing exactly those inverse changes. If something else has changed the same lines in the meantime, Git pauses and asks you to resolve the conflict by hand, exactly as it would during a conflicting merge — once resolved, you tell Git to continue, and it finishes creating the revert commit.
The resulting new commit typically has a default, auto-generated message such as “Revert ‘<original commit message>'” along with a reference back to the original commit’s identifier, so anyone reading history later can trace exactly which change is being undone and why, if a reason was added.
Because the result is an ordinary new commit — not a special, hidden operation — it behaves exactly like any other change in every way: it can be pushed, reviewed through a pull request (as covered in a related guide on code review), tested by automation, and even reverted again later if it turns out the revert itself was a mistake.
5Data Flow & Lifecycle of a Reverted Change
Original Commit Is Made
A developer commits a change — say, updating a pricing calculation — and it’s reviewed and merged into the shared branch.
Others Pull the Change
Teammates download the updated shared branch, and it may also be deployed to a live environment, so multiple copies of this history now exist.
A Problem Is Discovered
The pricing calculation turns out to be wrong in a specific scenario, and the team decides the safest immediate fix is to undo it.
Revert Commit Is Created
An engineer runs git revert on the original commit, producing a new commit with the opposite changes, as detailed in Chapter 4.
Revert Commit Is Shared
The new commit is pushed and merged the same way any other change would be — reviewed, tested, and deployed — restoring the previous working behavior.
History Remains Complete
Anyone looking at the project’s history later sees both the original change and the revert, with a clear trail explaining what happened and why.
Notice that at no point in this lifecycle does anyone need to coordinate a special, risky history-rewriting operation across multiple copies of the repository — the revert commit simply flows through the system the same way any ordinary change does.
6Revert vs. Reset vs. Checkout: Telling Them Apart
Git has several commands that can feel like “undo,” but they behave very differently, and mixing them up on shared history can cause real problems. Understanding the distinction is one of the most valuable things a beginner can learn early.
git revert
- Adds a new commit that cancels out an old one
- Never removes or rewrites existing history
- Safe to use on shared, already-pushed branches
- Leaves a visible record of both the mistake and the fix
git reset
- Moves your branch pointer backward, discarding later commits from that branch’s history
- Rewrites history — the discarded commits effectively disappear from that branch
- Dangerous on shared branches others have already pulled
- Best suited for undoing local, not-yet-shared commits
git checkout (or its modern counterpart, git restore) is different again — it doesn’t create any new commit at all. It simply changes the files in your working directory to match some earlier snapshot, without altering the commit history whatsoever. It’s typically used to discard uncommitted edits or temporarily inspect an older version of a file, not to undo something that’s already been committed and shared.
| Command | Creates a New Commit? | Rewrites History? | Safe on Shared Branches? |
|---|---|---|---|
| git revert | Yes | No | Yes |
| git reset | No | Yes | No (generally unsafe) |
| git checkout / restore | No | No | Not applicable (no history change) |
Using git reset to “undo” a commit that has already been pushed and pulled by teammates can cause serious confusion: their copy of history will disagree with yours, and forcing your version onto the shared branch afterward can silently discard other people’s work. When in doubt about whether a commit has already been shared, treat it as shared and use git revert instead.
7Reverting More Than One Commit
Sometimes an entire sequence of commits — say, five commits that together implemented a feature — needs to be undone at once, not just one. Git allows reverting a range of commits, and it will attempt to apply the inverse of each one, typically working backward from the most recent commit in the range to the oldest, since each commit’s inverse needs to be applied to the state left by undoing the ones after it.
Reverting a whole range of commits is inherently riskier than reverting a single one, because the chance of a conflict rises with each additional commit involved, especially if other, unrelated changes have touched the same files since. It’s also worth knowing that reverting a merge commit — the special kind of commit created when one branch is merged into another — requires telling Git which of the merge’s two parent lines of history should be treated as the “mainline” to revert back toward, since a merge, unlike an ordinary commit, has two parents instead of one.
Undoing an Entire Feature
A team ships a new feature across a dozen commits, merged as one unit. Days later, the feature is found to have a serious, unresolved design flaw. Rather than trying to identify and reason about the exact overlapping changes across all twelve commits by hand, the team reverts the single merge commit that brought the whole feature in, cleanly restoring the branch to its pre-feature state in one step.
8When Revert Conflicts — And What That Means
A conflict during a revert happens for essentially the same reason a conflict happens during a merge: Git’s automatic, line-by-line matching can’t confidently decide how to apply the inverse changes, usually because the same lines of code have been modified again by some later commit. This isn’t a sign that anything is broken — it’s Git correctly recognizing that it needs a human judgment call rather than guessing.
When this happens, Git marks the conflicting sections directly in the affected files, pauses the revert partway through, and waits for you to manually decide what the final content should look like. Once you’ve edited the files to resolve the conflict and marked them as resolved, you tell Git to continue, and it finishes creating the revert commit exactly as it would have if there had been no conflict at all.
A revert conflict is Git’s way of saying “the code has moved on since this original change, and undoing it isn’t as simple as reversing lines mechanically — please look at this by hand.” It’s a feature, not a failure: it prevents the revert from silently producing broken or nonsensical code.
9Advantages, Disadvantages & Trade-offs
| Aspect | Advantage | Trade-off / Limitation |
|---|---|---|
| Safety on shared history | Never rewrites or removes existing commits | Leaves the original “mistake” permanently visible in history |
| Speed of response | Can undo a bad change in seconds, ideal for production incidents | Only undoes the code change — doesn’t fix any external side effects it already caused |
| Team clarity | Everyone sees exactly what was undone and can trace the reasoning | Reverting many small commits individually can clutter history with extra entries |
| Conflict handling | Surfaces genuine conflicts for human review rather than guessing | Reverting a large or old commit can require resolving multiple conflicts by hand |
| Reversibility | A revert can itself be reverted, restoring the original change if needed | Doesn’t remove the reverted feature’s traces from documentation, discussions, or other systems automatically |
The core trade-off to internalize: revert optimizes for safety and honesty of the historical record over a “clean-looking” history with no trace of mistakes. For nearly all shared, collaborative work, that trade-off is exactly the right one — the safety it buys is worth far more than tidiness.
10Security Considerations
Reverting a commit that introduced a security fix will bring back the original vulnerability. Before reverting any commit, it’s worth checking what that commit actually did — reverting the wrong commit, or reverting a security patch by mistake while trying to undo something else nearby, can silently reopen a known weakness.
Because a revert commit is an ordinary commit like any other, it should go through the same code review process described in a related guide before being merged into a shared or production branch — even in an urgent incident, a second set of eyes helps confirm the revert actually targets the right commit and doesn’t have unintended side effects.
It’s also worth remembering that reverting a code change does not automatically undo anything that change already caused outside of Git itself — for example, if a buggy commit already sent incorrect data to a customer or modified a database, reverting the code stops the bug from continuing, but doesn’t retroactively fix data that’s already been affected. Those consequences typically need to be handled separately.
11Design Patterns & Anti-Patterns Around Revert
The Revert-First-Investigate-Later Pattern treats revert as the immediate, default first response to any change that’s causing problems in a shared or production environment — restore the known-working state fast, then take the time to properly understand and fix the underlying issue without pressure.
The Revert-and-Reopen Pattern pairs the revert commit with reopening the original task or issue that introduced the problem, ensuring the underlying work isn’t simply forgotten once the immediate symptom is undone.
The Situation
A bad commit was pushed to a shared branch minutes ago, and a developer considers using history-rewriting commands to make it look like the mistake never happened.
Why This Becomes a Problem
Even a few minutes can be enough time for someone else to have already pulled that commit. Rewriting shared history after that point creates mismatched histories across different people’s copies, which can cause confusing errors or silently lost work later.
The Better Pattern
Once a commit has been pushed to a shared branch, default to git revert rather than history rewriting, even if it feels like “extra” history — the safety guarantee is worth the small cosmetic cost.
Common anti-patterns to avoid: the Silent Revert (undoing a shared change without any explanation in the commit message or team communication, leaving teammates confused about why something they were relying on disappeared); the Panic Reset (using history-rewriting commands under pressure during an incident, on a branch that’s already shared); and the Un-Reverted Revert (reverting a change temporarily during an emergency but never following up to properly fix or reintroduce the underlying work).
12Best Practices & Common Mistakes
Confirm the Right Commit
Double-check exactly which commit you’re targeting before reverting — reverting the wrong one can undo unrelated, still-needed work.
Write a Clear Message
Add context to the revert commit’s message explaining why the change is being undone, not just relying on the auto-generated default text.
Send It Through Review
Treat a revert commit like any other change — route it through code review before merging, even during an incident.
Track the Underlying Fix
Open or reopen a task to properly address the root cause, so the reverted work isn’t simply forgotten.
Look Beyond the Code
Consider whether the original commit caused any effects outside Git — like altered data — that the revert alone won’t fix.
Default to Revert on Shared Work
When a commit might already be shared, choose revert over history-rewriting commands, even if you’re not entirely sure.
Common mistakes beginners make: confusing revert with reset and accidentally rewriting shared history when they meant to undo a change safely; reverting a large range of commits without expecting or budgeting time for potential conflicts; and forgetting that the auto-generated revert commit message, while accurate, rarely explains the actual reasoning behind the decision to a future reader.
13Real-World & Industry Examples
Production Incident Response
At a company running a large consumer-facing website, a newly deployed change causes checkout to fail for a subset of users. The on-call engineer immediately reverts the responsible commit and redeploys, restoring service within minutes, well before the root cause has even been fully diagnosed.
Open-Source Maintenance
A maintainer of a widely used open-source library merges a contributor’s pull request that later turns out to break compatibility for many existing users. The maintainer reverts the merge commit, explains the compatibility concern in the revert’s description, and invites the contributor to resubmit an adjusted version.
Feature Rollback After a Failed Experiment
A product team ships a new feature behind the scenes, and early data shows it hurts a key metric rather than helping it. Instead of trying to hand-craft a series of undoing edits, the team reverts the merge commit that introduced the feature, cleanly restoring the previous, well-understood behavior.
Correcting a Configuration Mistake
A DevOps engineer accidentally commits a configuration change that misroutes network traffic. Because the change was already deployed by an automated pipeline, a plain file edit wouldn’t create a clear record — so the engineer reverts the specific commit, producing an auditable, unambiguous record of exactly when and why the routing was restored.
14Frequently Asked Questions
15Summary and Key Takeaways
What to Remember
- git revert undoes a commit’s effect by adding a new, opposite commit — it never deletes, hides, or rewrites the original commit.
- It exists specifically for safely undoing changes that may already be shared with other people or already deployed, where rewriting history would be dangerous.
- Internally, it computes the diff a commit introduced, calculates its inverse, and applies that inverse as a brand-new commit — falling back to a manual conflict-resolution step when needed.
- It is fundamentally different from git reset, which rewrites history and discards commits, and from git checkout/restore, which changes files without creating any commit at all.
- A revert can itself be reverted, and reverting a merge commit requires specifying which parent line of history is the mainline.
- Revert doesn’t undo external side effects — like data already changed by the original commit — only the code change itself.
- The default rule of thumb: once a commit is shared, reach for revert, not history-rewriting commands — the small cost of extra history entries is worth the safety it guarantees.