Source code

Revision control

Copy as Markdown

Other Tools

---
name: stack-split-commit
description: Split one large or hard-to-review commit into several commits that each stand on their own for review, in a git or a Jujutsu (jj) checkout. Use when asked to split a commit or patch, break up a big diff for review, or make a lumped commit more reviewable. One commit at a time - `stack-reorganize` restructures a whole stack.
allowed-tools:
- Bash(git log:*)
- Bash(git show:*)
- Bash(git diff:*)
- Bash(git status:*)
- Bash(git branch:*)
- Bash(git checkout:*)
- Bash(git restore:*)
- Bash(git commit:*)
- Bash(git rebase:*)
- Bash(git reset:*)
- Bash(git apply:*)
- Bash(jj log:*)
- Bash(jj show:*)
- Bash(jj diff:*)
- Bash(jj split:*)
- Bash(jj commit:*)
- Bash(jj new:*)
- Bash(jj describe:*)
- Bash(jj rebase:*)
- Bash(jj edit:*)
- Bash(jj abandon:*)
- Bash(jj restore:*)
- Bash(jj file show:*)
- Read
- Grep
- Glob
---
# Splitting a commit into reviewable pieces
Split without changing the final tree. Every prefix of the result has to leave
the tree building, linting and passing tests, and no commit may mention a
concept that only a later commit introduces.
Pick the cuts by the rules below, then follow the mechanics for this
checkout's version control system. Use jj where the checkout has a `.jj`
directory at its root: it rebases descendants for you and records conflicts
instead of halting. Do not fall back to git commands there even if available.
- Jujutsu (jj): `references/jj.md`
- git: `references/git.md`
## Split by concern, not by "new vs. deleted"
A reviewer checks a move or a replacement by diffing the new code against the
code it replaces, so both go in the **same** commit.
- A behavior-neutral **move**, such as inlining logic into a shared helper, is
one commit, old-out and new-in side by side.
- A genuine **shape change**, such as an IPDL message or a data-format swap, is
a separate commit, again with old and new together.
- A piece that both moves and changes behavior is split into the neutral move
and the behavior change.
## A cut may need code that neither end state contains
The intermediate state often needs code written for it alone: a
compatibility stub so the earlier commit still builds, or an interim form of a
function that neither the parent nor the target has. Write it; a later commit
removes it. Don't assume every piece falls out of the original diff.
## Revisit each piece's message
The original's message now over-scopes, since it still describes what moved
out: narrow it to its own piece, and write the new piece's message from
scratch. The `firefox-commits` skill says what a message contains; what the
split adds is a body line for what only the split made true, such as a claim
of behavior-neutrality for a moved piece or an ordering that looks incidental
but isn't. When a subagent builds the pieces, specify each subject and only
the bodies that are warranted.
## Review-tool side
Submitting the split creates the new revisions but leaves the stack's
parent/child edges where they were. `moz-phab reorg [start_rev] [end_rev]`
recomputes them from the local order and previews the changes before acting
(`docs/contributing/stack_quickref.md`).
**Stop if the preview proposes abandoning a revision.** `reorg` abandons every
revision that is in the remote stack but not in the local range (those already
abandoned excepted), and narrowing the range grows that set: a WIP tip above
the range and the landed floor of a partially-landed stack are remote-only
under any range. `--no-abandon` re-wires the edges without the abandon
transactions. Never re-push without explicit approval.
## Splitting a revision that is already in review
Keep the original revision on the piece that retains the subject, usually the
higher-level concept: it keeps the `Differential Revision` trailer, so its
revision updates in place with a smaller diff, and the extracted piece lands as
`(New)` below it. The submit does not make the retained revision depend on the
new one; `moz-phab reorg` does, per above. Revisit both messages as above.