Lesson 87 of 12115 min read

git revert: Creating a New Commit That Undoes a Previous Commit (Safe Undo)

Learn how git revert safely undoes a previous commit's changes by creating a brand-new commit, without ever rewriting existing history.

Author: CodersNexus

git revert: Creating a New Commit That Undoes a Previous Commit (Safe Undo)

Every undo mechanism covered so far in this course — restore, checkout, amend, rebase — has involved discarding or rewriting existing history in some way, which is exactly why the golden rule (previous lesson) restricts them to local, unshared commits. `git revert` is fundamentally different: it undoes a commit's changes by creating a brand-new commit, never touching or rewriting existing history at all, making it the safe, appropriate choice for undoing something that's already been shared.

Learning Objectives

  • Undo a specific commit's changes using git revert.
  • Explain why git revert is safe to use even on commits that have already been pushed and shared.
  • Handle a conflict that occurs during a revert.
  • Understand the special considerations involved in reverting a merge commit.

Key Terms to Know Before Using git revert

  • git revert <commit>: Creates a new commit that applies the inverse of a specified commit's changes, effectively undoing it without altering existing history.
  • Inverse changes: The opposite of what a commit did — lines that were added are removed, and lines that were removed are re-added, effectively cancelling out the original change.
  • Revert conflict: A conflict that can occur if content has changed since the commit being reverted, such that its inverse can't be cleanly applied.
  • Reverting a merge commit: A special case requiring you to specify which parent's history to treat as the 'mainline' when undoing a merge.

How git revert Actually Works

`git revert <commit>` takes a specified commit and creates a **brand-new commit** that applies the **inverse** of its changes — anything the original commit added is removed, and anything it removed is re-added — effectively cancelling out that commit's effect on the codebase, while leaving the original commit itself completely untouched, still fully present in the project's history:

```
git revert a1b2c3d
```

This is the critical distinction from every other undo mechanism covered in this course: `git revert` **never rewrites or deletes any existing commit** — it only ever adds a new one. This makes it fundamentally, unconditionally safe to use even on commits that have already been pushed and shared with collaborators, directly contrasting with `commit --amend` (Module 2) and `rebase` (this module), both of which are restricted by the golden rule specifically because they rewrite existing history. If a bug is discovered in a commit that's already been merged into `main` and pulled by the whole team, `git revert` is exactly the right tool: it adds a new, clearly-labeled commit undoing the problematic change, without disturbing anyone else's already-pulled history at all.

By default, `git revert` opens an editor for the new commit's message, pre-filled with a description referencing the original commit being undone (e.g., `Revert "feat: add discount calculation"`), which you can edit or accept as-is. Adding `--no-edit` skips this prompt, accepting the default generated message directly:

```
git revert --no-edit a1b2c3d
```

Just like cherry-pick and rebase, a revert can encounter a **conflict** — if the codebase has changed since the commit being reverted, such that its exact inverse can't be cleanly applied, Git pauses for manual resolution, followed by `git add` and `git revert --continue` (or `git revert --abort` to cancel), following the same familiar pattern as this module's other commit-replaying operations.

A special, slightly more involved case is **reverting a merge commit**. Because a merge commit has two parents, Git needs to know which parent's line of history should be treated as the 'mainline' to revert relative to — this is specified with the `-m` flag, typically `-m 1` to treat the first parent (usually the branch you merged *into*, like `main`) as the mainline being preserved, undoing the changes introduced by the *other* parent (the branch that was merged in):

```
git revert -m 1 <merge-commit-hash>
```

Getting this parent number wrong reverts the 'wrong direction', so it's worth double-checking with `git show <merge-commit-hash>` or `git log --graph` beforehand to confirm which parent represents which branch.

git revert: Visual Walkthrough

Draw a horizontal commit history: C1-C2-C3(buggy feature)-C4-C5(current). Draw an arrow labeled 'git revert C3' pointing to a NEW commit C6 appended after C5, labeled 'Revert "buggy feature" — applies the INVERSE of C3's changes.' Show C3 remaining fully intact and unchanged in its original position in the history, with a caption: 'Original commit C3 is NEVER removed or altered — the codebase's current state is undone via a new commit, not by rewriting history.'

git revert vs git reset: Key Differences

Aspectgit revertgit reset / rebase / amend (next lesson covers reset in depth)
Rewrites existing commits?Never — only adds a new commitYes — replaces or removes existing commits
Safe on already-pushed/shared commits?Yes, unconditionally safeNo — restricted by the golden rule
Effect on project historyAdds a clear, permanent record of the undoCan make it appear as though the undone work never happened
Typical use caseUndoing a problematic commit that's already sharedCleaning up local, not-yet-shared history

git revert: Command Syntax and Examples

# Undo a specific commit's changes with a new commit
git revert a1b2c3d
# Opens an editor pre-filled with: Revert "feat: add discount calculation"
# (edit or accept, then save and close)

# Skip the message editor, accepting the default
git revert --no-edit a1b2c3d

# Handling a conflict during revert
git revert a1b2c3d
# CONFLICT (content): Merge conflict in checkout.js
git add checkout.js
git revert --continue

# Reverting a merge commit (must specify the mainline parent)
git log --graph --oneline   # confirm which parent is the mainline first
git revert -m 1 7f8e9d0

Breaking Down the git revert Example

`git revert a1b2c3d` creates a new commit undoing that specific commit's changes, with an editor opening to confirm or adjust the auto-generated message. `--no-edit` shows the faster path when the default message is acceptable as-is. The conflict-handling block mirrors the same pattern from cherry-pick and rebase: resolve, stage, then use the operation's own `--continue` flag. The final example demonstrates reverting a merge commit specifically, first checking `git log --graph` to confirm which parent represents the mainline before specifying `-m 1`, since getting this wrong would undo the wrong branch's contribution.

How git revert Is Used on Real Engineering Teams

  • When a bug is discovered in a change that's already been deployed to production and pulled by the entire team, git revert is the standard, safe way to quickly undo it without disrupting anyone's local history.
  • Many teams' incident response processes explicitly specify reverting a problematic commit (rather than attempting a more complex manual fix under time pressure) as the fastest, safest way to restore a working state during an active production issue.
  • CI/CD systems sometimes automatically revert a commit if its deployment triggers a failing health check, using exactly this mechanism to quickly and safely roll back a bad change.
  • Open-source project maintainers commonly use revert (rather than a forced history rewrite) to undo a merged pull request that turns out to have unintended consequences, preserving a clear, honest historical record of both the original change and its later reversal.

git revert Interview Questions and Answers

Q1. What does git revert do, and how does it differ fundamentally from rebase or amend?

git revert creates a brand-new commit that applies the inverse of a specified commit's changes, undoing its effect while leaving the original commit completely untouched in history. This differs fundamentally from rebase or amend, which rewrite or replace existing commits — revert never alters existing history, only adds to it.

Q2. Why is git revert considered safe to use even on commits that have already been pushed and shared?

Because it never rewrites or deletes any existing commit — it only adds a new one undoing the previous change. This means it doesn't create the diverged-history problem that rebase or amend can cause on shared commits, making it unconditionally safe regardless of who else has already pulled the original commit.

Q3. What extra consideration is required when reverting a merge commit?

Since a merge commit has two parents, Git needs to know which parent's line of history to treat as the mainline being preserved, specified with the -m flag (commonly -m 1). Getting this parent number wrong would undo the wrong branch's contribution, so it's worth confirming the correct parent with git log --graph beforehand.

git revert Quiz: Test Your Understanding

1. What does git revert do to the commit being reverted?

  1. Deletes it permanently from history
  2. Leaves it completely untouched, adding a new commit that undoes its effect
  3. Rewrites it with a new hash
  4. Moves it to a different branch

Answer: B. Leaves it completely untouched, adding a new commit that undoes its effect

Explanation: git revert never alters or removes the original commit — it only adds a new commit applying the inverse of its changes, leaving existing history fully intact.

2. Why is git revert considered safe for commits that have already been pushed and shared?

  1. It doesn't actually change anything in the codebase
  2. It never rewrites existing history, only adds a new commit, avoiding the diverged-history problem rebase or amend can cause
  3. Git technically prevents reverting shared commits
  4. It requires special permissions unavailable to most users

Answer: B. It never rewrites existing history, only adds a new commit, avoiding the diverged-history problem rebase or amend can cause

Explanation: Since revert only adds new history rather than rewriting existing commits, it doesn't create the hash-mismatch problem that makes rebasing or amending shared commits risky.

3. What must you specify when reverting a merge commit, and why?

  1. A new branch name, to avoid conflicts
  2. Which parent to treat as the mainline, using the -m flag, since a merge commit has two parents
  3. The original author's email
  4. Nothing extra — merge commits revert exactly like regular commits

Answer: B. Which parent to treat as the mainline, using the -m flag, since a merge commit has two parents

Explanation: Because a merge commit has two parent commits, Git needs to know which one represents the mainline being preserved (commonly specified as -m 1), or the revert could undo the wrong branch's contribution.

Common git revert Mistakes Beginners Make

  • Confusing revert with reset or rebase, expecting it to rewrite or remove history when it actually only adds a new, undoing commit.
  • Forgetting to specify the -m flag when reverting a merge commit, or specifying the wrong parent number, undoing the wrong branch's changes.
  • Not resolving revert conflicts using the correct --continue/--abort commands specific to the revert operation.
  • Reaching for a riskier tool like rebase or amend to undo an already-shared commit, when revert would accomplish the same goal safely.

git revert: Exam-Ready Quick Notes

  • git revert <commit>: creates a NEW commit applying the inverse of the specified commit's changes; original commit is never altered.
  • Safe on already-pushed/shared commits, unlike rebase or amend, since it never rewrites existing history.
  • --no-edit: skip the commit message editor, accepting the auto-generated default message.
  • Reverting a merge commit requires -m <parent-number> to specify the mainline; check git log --graph first to confirm the correct parent.

git revert: Key Takeaways

  • git revert is the safe, appropriate way to undo a commit that has already been pushed and shared, since it never rewrites existing history.
  • Unlike rebase or amend, revert adds a new commit rather than replacing an existing one, making it unconditionally safe regardless of who else has the original.
  • Reverting a merge commit requires the extra step of specifying which parent represents the mainline, since a merge commit has two parents.

Frequently Asked Questions About git revert

Q1. What does git revert do?

It creates a new commit that undoes the changes introduced by a specific earlier commit, applying the exact inverse of what that commit did, while leaving the original commit completely unchanged and still present in the project's history.

Q2. Why is git revert safer than rebase or amend for undoing a commit?

Because revert never rewrites or removes any existing commit — it only adds a new one. Rebase and amend both replace existing commits with new ones bearing different hashes, which is risky on commits that have already been shared with collaborators; revert avoids this risk entirely.

Q3. Can I use git revert on a commit that's already been pushed and pulled by my team?

Yes, this is exactly what revert is designed for — it's unconditionally safe to use on already-shared commits, since it doesn't rewrite any existing history, only adds a new commit undoing the problematic change.

Q4. How do I revert a merge commit?

Use the -m flag to specify which parent represents the mainline being preserved, typically git revert -m 1 <merge-commit-hash>. It's worth checking git log --graph first to confirm which parent is actually the mainline, since specifying the wrong one would undo the wrong branch's changes.

Q5. What happens if a revert causes a conflict?

Resolve the conflict in the affected file just as you would during a merge or rebase, stage the resolved file, and run git revert --continue to proceed. You can also run git revert --abort to cancel the operation entirely if needed.

Summary

`git revert <commit>` safely undoes a specific commit's changes by creating a brand-new commit that applies the inverse of what the original commit did, while leaving that original commit completely untouched in history. This is the critical distinction from every other undo mechanism covered in this course — revert never rewrites or removes existing commits, only adds to history — making it unconditionally safe to use even on commits that have already been pushed and shared with collaborators, unlike `commit --amend` or `rebase`, which are restricted by the golden rule. Reverts can encounter conflicts, resolved with the same familiar resolve-then-continue pattern (`git revert --continue` or `--abort`). Reverting a merge commit requires an extra `-m <parent-number>` flag specifying which parent to treat as the mainline being preserved, since a merge commit has two parents — worth confirming with `git log --graph` beforehand to avoid undoing the wrong branch's contribution.

Frequently Asked Questions

It creates a new commit that undoes the changes introduced by a specific earlier commit, applying the exact inverse of what that commit did, while leaving the original commit completely unchanged and still present in the project's history.

Because revert never rewrites or removes any existing commit — it only adds a new one. Rebase and amend both replace existing commits with new ones bearing different hashes, which is risky on commits that have already been shared with collaborators; revert avoids this risk entirely.

Yes, this is exactly what revert is designed for — it's unconditionally safe to use on already-shared commits, since it doesn't rewrite any existing history, only adds a new commit undoing the problematic change.

Use the -m flag to specify which parent represents the mainline being preserved, typically git revert -m 1 <merge-commit-hash>. It's worth checking git log --graph first to confirm which parent is actually the mainline, since specifying the wrong one would undo the wrong branch's changes.

Resolve the conflict in the affected file just as you would during a merge or rebase, stage the resolved file, and run git revert --continue to proceed. You can also run git revert --abort to cancel the operation entirely if needed.