Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXIV · RevertFoundations

Revert without committing — staging the inverse with `git revert -n`

Advanced⏱ ~18 mingit

What you'll learn

  • Explain what `git revert -n <commit>` (also `--no-commit`) does to the index and the branch tip
  • Identify the production use cases for staging a revert without committing: combining multiple inverses, splitting a revert across commits, and combining a revert with related fixes
  • Use `git revert -n` followed by `git commit` to record a single commit that combines the inverses of several commits
  • Recognise that `--no-commit` leaves you in a normal working state, not a revert-in-progress state, so `--continue` is not available
  • Distinguish `git revert -n` (stage the inverse, no commit) from `git revert --continue` (resume a multi-commit revert after conflict resolution)

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

git revert -n <commit> (also --no-commit) does everything git revert <commit> does except create the revert commit. It applies the inverse of <commit> to the working tree, stages the inverse in the index, and stops. The branch tip does not move. No commit is created. The engineer is now in a normal working state with the inverse staged, free to combine it with other changes, split it into multiple commits, or amend it before recording.

The default git revert workflow assumes one revert equals one commit. The -n workflow assumes the engineer may want to do something more interesting: collapse several reverts into one reviewable commit, combine a revert with a forward fix, or split a revert into separate logical commits. None of those is possible without staging without committing first.

The shape of a no-commit revert

git revert -n <commit> runs the three-way merge, applies the inverse to the working tree, and stages the result. The branch tip is unchanged. The index contains the inverse; git status shows the inverse as “Changes to be committed”:

COMMIT=abc1234
git revert -n $COMMIT
git status
# On branch main
# Your branch is up to date with 'origin/main'.
#
# Changes to be committed:
#   modified:   service.yaml
#   modified:   iam.tf
#   deleted:    policies/feature.rego
#
# no changes added to use git commit (use "git add" and/or "git commit -a")

The next command is git commit (or git commit -m "..."), which records the staged inverse as an ordinary commit. The commit’s parent is the current branch tip — the same parent it would have had if git revert <commit> had run without -n. The only difference is that the engineer has full control over the commit message and the staging area between the revert and the commit:

COMMIT=abc1234
git revert -n $COMMIT
git commit -m "Revert \"$ORIGINAL\" due to CVE-2024-XXXX

This reverts commit $COMMIT.
Refs: INC-1234"

The resulting commit is functionally identical to one produced by git revert <commit> without -n — it has the same parent, the same tree diff, and the same effect on the tree at HEAD. The difference is in the workflow that produced it: the engineer had a chance to inspect, modify, and stage the inverse before committing.

When to use -n

There are four production workflows where -n is the right choice:

flowchart LR
    A["git revert -n"] --> B["Stage the inverse"]
    B --> C{"What next?"}
    C -- "single commit" --> D["git commit"]
    C -- "combine with fix" --> E["edit, git add, git commit"]
    C -- "split into pieces" --> F["git reset, partial git add, multiple commits"]
    C -- "combine multiple reverts" --> G["revert -n each, git commit once"]
  1. Combining multiple reverts into one commit. When several commits need to be undone as a single logical rollback, git revert -n each in sequence and then git commit once. The result is one revert commit that names multiple original commits in its message, which is easier to review and easier to revert later.
  2. Combining a revert with a forward fix. When the revert is part of a larger change (for example, reverting a feature and replacing it with a fixed version), -n lets you stage the inverse, then stage the fix on top, then commit both as one logical change. The audit trail is one commit, not two.
  3. Splitting a revert into separate commits. When the inverse touches multiple files that should be reviewed separately, git revert -n then git reset (to unstage) then git add -p to stage hunks selectively. The result is several commits that each revert a logical slice of the original.
  4. Inspecting the inverse before committing. When the original commit is large or unfamiliar, -n lets you read the staged diff with git diff --cached before deciding whether to commit, amend, or discard.

Multi-commit reverts without -n

For contrast: git revert <commit-A> <commit-B> <commit-C> (default, no -n) creates three separate revert commits in sequence, stopping for conflict resolution if needed. The first commit inverts <commit-A>; the second inverts <commit-B> (applied on top of the first); the third inverts <commit-C>. Each commit has the default “Revert …” message. The result is three reviewable, individually revertible commits — but three separate audit-trail entries, three CI runs, three deployments.

git revert abc1234 def5678 9abcdef
# produces three revert commits, one per original

git revert -n collapses this into one commit:

git revert -n abc1234
git revert -n def5678
git revert -n 9abcdef
git commit -m "Revert feature X (commits abc1234, def5678, 9abcdef)"
# produces one revert commit whose message names all three

The choice between “many small revert commits” and “one combined revert commit” is a team-policy decision. Small reverts are easier to revert-of-revert individually; combined reverts are easier to review and reason about. -n is the tool for the combined case.

UnderTheHood: what -n actually skips

The default git revert <commit> flow runs the three-way merge, applies the inverse to the index, creates a commit object with the staged tree, updates the branch tip to point at the new commit, and reports the new OID. git revert -n <commit> does everything except the last two steps. The commit object is never created; the branch tip is never updated. The internal state after -n is identical to the internal state after a successful three-way merge in a git merge workflow: working tree and index updated, branch tip unchanged, ready for the next commit.

Production discipline

The production discipline for git revert -n has three rules:

  1. Use -n when the revert must be combined with other changes. A revert that is the only change in a commit should use the default flow; a revert that is part of a larger change (forward fix, multi-commit rollback, split-by-file revert) should use -n.
  2. Write the commit message after staging, not before. The -n workflow gives you a chance to inspect the inverse; the commit message should describe what is actually in the index, not what you expected the inverse to be. Use git diff --cached to verify before committing.
  3. Do not use -n to defer the commit indefinitely. A long-lived -n revert in the index is a revert that has not been audited, reviewed, or deployed. Commit it or discard it; do not leave it staged across multiple sessions.

Cross-course references

  • Git, CI/CD & GitOps — Part IX (Three-way merges) — the three-way merge that produces the inverse is the same merge that powers git merge and git cherry-pick; -n is a post-merge, pre-commit hook for the result.
  • Git, CI/CD & GitOps — Part VI (Index)-n leaves the inverse in the index; the staging area is the engineer’s workspace for combining the inverse with other changes.
  • Git, CI/CD & GitOps — Part XIII (Cherry-pick)git cherry-pick -n <commit> is the same workflow as git revert -n <commit>; both stage a patch without committing.
  • Terraform for Production Sysadmins — Part IX-XII (State) — when reverting a Terraform-bearing commit, -n lets you stage the inverse and then add manual terraform state adjustments to the same commit, producing one rollback commit that addresses both the code and the state.

Quiz

Knowledge check · 4 questions

  1. Q1. An engineer needs to revert three commits (`abc1234`, `def5678`, `9abcdef`) and combine the inverses into a single reviewable commit. What is the cleanest workflow?

  2. Q2. After `git revert -n <commit>`, you are in a revert-in-progress state and must run `git revert --continue` to finish.

  3. Q3. Name the flag that stages the inverse of a commit without creating a commit, and state where the inverse is staged.

  4. Q4. Plan the rollback of a feature that introduced a broken IAM policy, where the rollback must also include a one-line forward fix to an unrelated file that was edited in the same release.

    Release `v3.2.0` introduced a broken IAM policy via commit `i4m0a11` and an unrelated typo fix via commit `t1y0o11`. The team needs to roll back the IAM policy but keep the typo fix. The rollback must be a single reviewable commit because the team requires one CI run per rollback.

Passing score: 75%. Answers are checked in this browser.