Structuring PRs with Narrative Commits

01 Intro

I like using what I call narrative commits (and others have called literate commits) to make a PR tell a story. This is helpful for reviewers and for me while working on a PR. If my commits tell a story, it’s easier for me to start working on a PR again after a context switch and for reviewers to quickly grasp what the PR is changing. It also gives reviewers the possibility to review the PR commit by commit instead of only looking at the full diff.

02 Mystery Meat

I find it difficult to review PRs that do not have a description, and where I cannot look at the commit history to understand what the PR is doing. I do not know what’s inside, until I start dissecting it. Like mystery meat. The only option I have is to look at the complete diff. This works for smaller PRs, but gets difficult quickly for bigger PRs.

03 Narrative Commits

A good first step to reduce the mystery is to write a description for the PR. The next step is to make the commits tell a story. You make commits tell a story by ensuring each commit does only one thing (atomic commits) and by writing concise commit messages. My story usually starts with some refactoring to prepare for the changes that I’m about to make. Then, when possible, I add failing tests. Finally, I implement the changes to make the tests pass. Here’s an example:

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

I like continuously rebasing my PR while I’m working on it. I usually don’t know the exact story I want to tell when starting, but it becomes clearer as I make progress. When I feel like the story in my head is diverging from the story my commits are telling, I rebase. This can happen multiple times while working on a PR. I like using the interactive rebase tool in the JetBrains IDEs for this, but I when I started doing this I did it with the git cli directly.

Berlin 10 August 2025