Atomic commits make reviewable PRs
Othman Shareef · July 6, 2026 · 6 min read · The Craft of Code Review
There are two kinds of multi-hundred-line PRs: the kind reviewers dread, and the kind that reads like a well-edited essay, because the author structured it as a sequence of commits, each one a chapter. Same total diff, wildly different review cost. The difference is a craft most teams never discuss, though the squash-versus-history argument that surrounds it flares up reliably whenever review workflow comes up.
Why structure beats size
We’ve argued smaller PRs review better, but some changes are legitimately medium-sized, and the next lever after size is order. A flattened diff mixes the mechanical with the meaningful: the rename touches 30 files, the real semantic change touches two, and the reviewer must discover which is which line by line. Commit structure is the author telling the reviewer, credibly: these 30 files are the rename; trust them as a unit; spend yourself on these two. It’s the same triage we recommend reviewers do on their side, except the author, who knows the answer, does it once for everyone.
The recipe
- Separate refactor from behavior. The cardinal rule. “No behavior change” commits get verified structurally; behavior commits get scrutiny. Mixed, they poison each other.
- Mechanical bulk gets its own commit (renames, formatting, codemods, generated files), labeled as such in the message.
- Messages carry the why. As one HN commenter put it, commit messages are the developer docs for a change. “Switch to exponential backoff because the flat retry hammered the API during outages” reviews itself.
- Curate before requesting review. Your fifty “argh, forgot this bit” commits are fine while working.
git rebase -ithem into the story before asking for eyes. (During review rounds, switch to append-only fixups; see the interdiff piece.)
The squash debate, defused
“Why bother if we squash-merge anyway?” Because the commits’ job is during review: they’re the author’s table of contents for the reviewer. What main’s history looks like afterward (one squashed commit, or the curated sequence) is a separate policy decision with its own trade-offs (bisectability and revert granularity vs. a linear, tidy log). Both camps can be right at their own moment in the timeline. The only losing position is chaotic commits and a flattened review.
Reviewing commit-by-commit in practice
The workflow needs tool support to stick: stepping through commits, and scoping the diff to a single commit or a span when you need to re-check one chapter. GitHub allows per-commit viewing but loses your thread positions between scopes; it’s one of the flows we built deliberately into Pyor (ours, free for individuals): pick any commit or range in a PR and the diff re-scopes to it, threads intact. Author structures the story; reviewer reads it chapter by chapter; nobody re-reads the book.