The Power of Small PRs

The data shows that small PRs increase velocity

Date

Aug 30, 2024

Cat reviewing code
Photo by Volodymyr Dobrovolskyy on Unsplash

I was recently looking at data from tens of thousands of pull requests (PRs) and it got me thinking about how we could speed up our development.

As I looked at the different PRs, the time it took for them to get reviewed, the time it took for them to get merged, and the number of changes requested I noticed a consistent trend. Smaller PRs let orgs move faster.

And so I started wondering - are we slowed down by big PRs?

The Data Doesn't Lie

In our analysis, we found repositories with wildly different approaches to code changes. From very small PRs (I've anonymized the repo names here) :

  • Repo A: Average 40.85 lines modified per PR
  • Repo B: Average 43.33 lines per PR
  • Repo C: Average 50.28 lines per PR

To massive PRs - thousands of lines per PR.

  • Repo D: 6,547 lines per PR
  • Repo E: 6,764 lines per PR
  • Repo F: 46,374 lines per PR (and this isn't a one off, this is over more than 70 PRs in the last month)

Now, I'm not here to shame anyone for big PRs. Sometimes they're necessary. But these orgs with smaller PRs? They're onto something.

The smaller the PR the orgs worked with, the faster their time to merge changes. On average, the lead time to merge for a PR under 150 lines was 40% quicker than for PRs 150-300 lines. And that trend held as PRs got bigger.

Why Small Changes Matter

There are a couple of reasons why smaller PRs give an advantage.

  • Reviews are a breeze: Ever tried to review a 1000+ line PR? It's like trying to find a needle in a haystack. Small PRs are easier to understand and review. We found that repos with lower average lines modified often had quicker merge times.
  • Less risky business: Smaller changes mean smaller risks. If a bug sneaks in, it's way easier to spot and fix when the change is minimal.
  • Faster feedback loop: With smaller, more frequent PRs, you're getting feedback quickly. It's like having a conversation with your team instead of giving a monologue.
  • Play nice with CI: Small changes align beautifully with continuous integration. You're testing and deploying more frequently, catching issues early.

Are We Being Slowed Down?

Looking at the data for our own repos it looked like there's some clear room for improvement. Our average PR had ~344 lines changed. But digging a bit deeper it showed that this wasn't a consistent problem.

The vast majority of our PRs were under 100 lines, but we had some much bigger PRs that drove that average up. Some of those big PRs were fine - the bulk of their size was data inputs used for various tests we do, they weren't actually giant code changes.

But about 10% of our PRs were for new functionality and were larger PRs. And when I looked at those I realised they tended to be features that were taking us a while to develop and where we wound up having lots of internal feedback about the way we were approaching the implementation when the PR was finally reviewed.

Even if we were pretty good about opening small PRs in general, there still is an opportunity to shift even further to keeping our PRs tight.

Making the Shift

So, how do we move towards this incremental approach? Here are some strategies I've seen work:

  1. Break it down: Encourage your team to slice larger features into smaller, manageable tasks.
  2. Set some guidelines: Consider setting a soft limit on PR sizes. Maybe aim for under 200 lines as a starting point?
  3. Commit often: Even if you're not ready to open a PR, commit your changes frequently.
  4. Automate where you can: Tools like Sourcery (shameless plug, I know) and others can help automate reviews for small, routine changes.
  5. Celebrate the small wins: Recognize when team members are consistently making small, impactful changes. It reinforces the value of incremental progress.

But What About Those Big Changes?

Now, I'm not saying you should never make big changes. Sometimes they're unavoidable. Maybe you're doing a major refactor or implementing a complex feature. That's fine.

The key is to make these larger changes the exception, not the rule. And when you do make them, approach them with extra care and a thorough review process.

Wrapping Up

At the end of the day, our goal is to ship good code quickly and reliably. Our data is showing a clear trend: repositories that consistently make small, incremental changes often benefit from smoother review processes, quicker merge times, and likely, more stable codebases.

By embracing incremental development, we can create a more agile, responsive, and collaborative environment. It's not just about the code - it's about how we work together.

I'm curious - have you tried pushing for more incremental changes in your team? What challenges did you face? Let me know in the comments. I'm always looking for new perspectives on this!