Narrative Commits: How I Structure PRs for Fast Reviews

Reviewers shouldn’t reverse-engineer your intent. Narrative commits turn a PR into a readable story.

Bad pattern: flat PRs

  • What I mean by “flat”: commits don’t tell a story, just a pile of diffs with unclear intent or order
  • Huge diff, 1–2 commits
  • Or: 30+ commits where many are noise (lint/format/import fixes)
  • Mixed refactors/logic/tests in the same commits
  • Vague messages
  • Hard to review, easy to miss bugs

Good pattern: narrative commits

  • Each commit does one thing and advances the story
  • Clear, imperative messages with intent
  • Order commits so they read like a progression. For me this often looks like this
    1. refactor to prepare for changes
    2. add failing tests
    3. implement change in functionality
  • Less guessing for reviewers means more bugs caught and better and quicker feedback

Narrative commits: an example

extract the csv parser from the handler to set up isolated changes
add support for multiple pool assignments - add failing tests
add support for multiple pool assignments - implement
handle overlapping assignments - add failing tests
handle overlapping assignments - implement

How I structure commits

  • Make commits tell a story
    • One purpose per commit. Usually: refactor, implement, or test.
    • Keep refactors separate from behavior changes.
  • Write focused messages
    • Use imperative: “add support…”, “handle…”, “extract…”.
    • Add a short “why” when it’s not obvious.
  • Remove noise the noise of typo/lint-only commits.
  • Ask reviewers to review commit-by-commit.

Make it happen: continuous interactive rebase

  • Don’t wait for a big cleanup at the end. Shape the branch as you go as the story becomes clear.
  • Amend a previous commit or use interactive rebase to keep a clean commit history
  • Recommended: The interactive rebase tool in JetBrains IDEs
  • CLI alternative: git rebase -i

PR descriptions: right-size the context

  • The stronger the commit narrative, the lighter the description can be.
  • Minimal (you paired/already synced): “Paired with X. Review commit-by-commit; focus on Y.”
  • Brief (most cases): why now, scope boundaries, risks, testing notes, links; include screenshots for UI/API changes.
  • Detailed (bigger impact): problem, approach/tradeoffs, alternatives, migration/observability.

What if I quash on merge?

Still worth it. Review happens before merge; the narrative benefits reviewers and future you regardless of merge strategy.