Git Revert
Undo a published change with revert, keep shared history intact, and reserve rewrite commands for commits nobody else has.
Two meanings of undo
Public and private describe dependency
A commit is not safe to rewrite merely because a repository is called private. The important question is whether another person, clone, automation, deployment, or review already depends on that commit ID and ancestry.
Only your local branch depends on it
- Not pushed to a shared ref.
- Not used by another worktree or automation.
- No review or release cites the commit.
- You can account for every descendant.
Another system may depend on it
- Published to a branch others fetch.
- Used in a pull request, build, or deployment.
- Referenced in an issue or release.
- Another contributor may have based work on it.
Inspect before choosing an undo
git status
git log --oneline --decorate --graph --all
git show --stat <commit>
git show <commit>
# Local evidence of which branches contain the commit
git branch --contains <commit>
git branch -r --contains <commit>Containment output is evidence from the refs currently available in this clone. Remote-tracking refs can be stale until fetched, and another person’s local branch is invisible. Combine commands with team and deployment context.
IDENTIFYName the exact bad commitRead its full patch, parent, message, author, and descendants instead of selecting it by date alone.
CLASSIFYDecide whether history is sharedCheck refs, pull requests, builds, deployments, and collaborators—not just the current branch.
PREDICTState the desired final treeAn inverse patch may not equal “restore the entire project to how it looked then.”
VERIFYPlan post-operation evidenceKnow which log, show, diff, test, and status results will prove success.
Revert records a corrective commit
git revert COMMIT calculates the selected commit’s change relative to its parent, attempts to apply the inverse to the current tree, and creates a new commit. The original commit remains reachable; the branch gains a descendant that counteracts it.
# Create a new commit that inverses one earlier commit
git revert <commit>
# Verify the new history and resulting patch
git show --stat HEAD
git diff HEAD^ HEAD
git log --oneline --decorate --graph -5A → B → C
B introduced a defect. C contains later work that must remain.
A → B → C → R
R inverses B against the current tree. B, C, and the correction remain visible.
Test what you learned
Type the command that creates a corrective commit reversing 8f42d91.
An inverse patch is not time travel
Reverting B does not reset the entire project to B’s parent snapshot. It applies B’s inverse while retaining unrelated changes from later commits. If later work depends on B or changed the same lines, the result may conflict or require additional correction.
Original addition
If B added a line, the inverse normally removes it from the current tree.
Original deletion
If B deleted a line, the inverse normally restores it when current context allows.
Original modification
The inverse attempts to replace B’s new side with its old side, while respecting later context.
Later dependency
Tests may fail even after a clean revert if later behavior was built on the reverted change.
Resolve a revert conflict by desired behavior
A revert can conflict when the current tree no longer provides context for the inverse patch. Conflict markers show competing content, but the correct answer is the intended current behavior—not automatically “ours,” “theirs,” or the oldest text.
git status
# Open each conflicted file and produce the intended current result
git add path/to/resolved-file
git revert --continue
# Or abandon the in-progress revert and restore its pre-revert state
git revert --abort- 01Read the target commit again
Identify exactly which behavior is being counteracted and which later behavior must remain.
- 02Inspect every conflicted path
Remove markers and produce valid current content, including dependent files the automatic patch did not flag.
- 03Stage resolutions
Use diff and cached diff to prove the inverse plus your resolution matches the intended correction.
- 04Continue and test
Complete the sequencer, run relevant checks, and inspect the resulting commit.
Review or combine inverse changes before committing
git revert --no-commit <commit>
git status
git diff
git diff --cached
# After reviewing and testing the prepared inverse:
git commit -m "Revert checkout validation regression"--no-commit prepares the inverse in the index and working tree without creating the final revert commit. This is useful when a correction needs an accompanying compatibility edit or when several tightly related inverse changes should be reviewed together.
Reset rewrites the current branch
git reset TARGET moves the current branch to another commit. Depending on mode, it may also update the index and tracked working tree. The old commits may still exist in reflog or other refs, but they are no longer descendants of the rewritten branch tip.
A → B → C
The current branch points to C.
branch → A
B and C are no longer reached from that branch. Mode determines the index and working-tree result.
Reset can be appropriate when B and C are unpublished local mistakes and you intend to rebuild them. On a shared branch, moving back to A creates ancestry disagreement: another clone may still point to C and a push commonly requires history-overwriting coordination.
Choose from the collaboration state
Shared bad commit
Use revert so everyone can receive a new descendant through normal history integration.
Private latest commit
Amend when it is one local snapshot or message correction and the replacement is clear.
Private series to rebuild
Reset only after preserving wanted work and choosing soft or mixed state deliberately.
Only a file state is wrong
Use restore or a new file correction. Do not rewrite an entire branch for a path-level problem.
Bad change plus later dependencies
Plan a corrective commit or revert with follow-up edits and tests; a mechanical inverse may be insufficient.
Uncertain sharing status
Treat history as shared until refs, reviews, deployments, and collaborators establish otherwise.
Reverting a merge is an advanced decision
A merge commit has multiple parents, so Git needs a mainline parent to define which side’s perspective remains. The command form is git revert -m 1 MERGE_COMMIT, where 1 is a parent number—not a commit ID and not automatically “main.”
git show --no-patch --pretty=raw <merge-commit>
git show --first-parent <merge-commit>
# Only after verifying which parent is the intended mainline:
git revert -m <parent-number> <merge-commit>Guided practice: undo without rewriting
Use a disposable repository. Create a baseline commit, a commit that introduces a visible defect, and a later unrelated documentation commit.
- 01Prove the graph
Identify the defect commit and show why the later documentation commit must remain.
- 02Inspect the patch
Use show and path-limited history to describe the exact behavior to reverse.
- 03Revert the defect
Create the corrective commit, inspect its patch, and confirm the documentation still exists.
- 04Verify history
Draw the graph and explain why the original defect and correction both remain reachable.
- 05Test the final tree
Run a relevant check or make a repeatable manual assertion proving the behavior is corrected.
Independent lab: simulate a shared regression
Create a disposable repository with a bare local remote and two clones representing two collaborators. Build and push a three-commit history where the middle commit introduces a defect and the final commit adds valid independent work. Then:
- Fetch in both clones and record the common published graph.
- Identify the defect commit by ID and inspect its complete patch.
- Create and push a revert from the first clone without rewriting the branch.
- Fetch and integrate normally in the second clone.
- Prove both clones reach the original commit, later work, and corrective commit.
- Create a separate unpublished practice branch and demonstrate how reset changes its reachable graph.
- Explain why force-pushing the reset branch over the shared branch would create a coordination problem.
- Finish with clean status and matching shared branch tips in both clones.
Common undo mistakes
Resetting because revert feels noisy
Visible correction is useful audit evidence. A shorter graph is not worth breaking shared ancestry.
Reverting the wrong commit
Dates and messages are not enough. Inspect the object ID, parent, patch, and affected paths.
Assuming no conflict means correct
The inverse can apply cleanly while later behavior still depends on what was removed. Run tests.
Choosing conflict sides mechanically
Conflict labels do not encode product intent. Produce the desired current behavior deliberately.
Reverting a merge without parent analysis
The mainline number changes the inverse and future merge behavior. Inspect parents and coordinate first.
Treating remote-tracking refs as live truth
They reflect the last fetch and cannot reveal every collaborator’s local dependencies.
Lesson review
You can now choose an undo strategy from collaboration evidence. Revert adds an auditable correction to shared history; reset moves a private branch when its old ancestry has no external dependents. Both require exact commit identification, a predicted final tree, and verification after the operation.
- I classify history by dependency, not repository visibility or force-push permission.
- I know revert preserves the original commit and adds an inverse change.
- I reserve reset-based rewriting for unpublished history I can fully account for.
- I resolve revert conflicts from intended current behavior and run relevant tests.
- I treat merge reverts as coordinated changes with future integration consequences.