
A classic xkcd comic. ([source](https://xkcd.com/386/))
A while ago, someone was wrong on the Internet, and I couldn’t let it go1. 😄 A LinkedIn post asked whether small PRs are only justified for hotfixes, or if they have broader value, and what the maximum number of changed files should be before a PR gets pushed back for splitting.
Beyond the obvious point that the number of files is irrelevant, I think a pull request’s upper size limit depends on the change’s complexity2 and on keeping feedback loops short.
When people think about feedback loops in the flow of software engineering, there is a tendency to only focus on the explicit customer feedback loop. “Put it in the hands of the customer ASAP!”, they say. But what is “it”, really? Most people think of “it” as “the new customer feature”. I think of it as “a change”, any change really. For example, if you have refactored some code, ship it immediately. Or, if you have discovered a bug while implementing a new feature, ship that bug fix immediately.
Feedback is not only from your customers Link to heading
So what is feedback in terms of shipping code, really? I think people have this mental model when developing software (or any product, really):
The above mental model figure is really too simplified. For anyone who has read the classic book Continuous Delivery by Jez Humble and David Farley, you know that shipping software can be thought of as a pipeline:
Notice all the arrows pointing left towards the Developer. That’s all feedback. Feedback is not just coming from the customer. Feedback comes from every step of the system that is shipping your changes from left to right.
Every step along the pipeline adds more certainty that the change works as intended. The earlier in the pipeline a mistake is caught, the faster the feedback back to the developer.
Smaller increments mean quicker feedback Link to heading
for each desired change, make the change easy (warning: this may be hard), then make the easy change
— Kent Beck 🌻 (@KentBeck) September 25, 2012
Can we get even faster feedback? Yes, by shipping smaller increments often. The smaller your change is, the faster it will take for you to figure out what is broken. If you changed 100 if conditions, debugging is hard, because the bug could be in any of them. If you changed two, it’s a whole lot easier. More changes mean more places the bug could be. And you can notice and fix performance regressions earlier, instead of at launch.
Also, smaller changes tend to be less error-prone - it makes your product far more stable over time. And easier to roll back. How many times have we, as an industry, coded away on a giant pull request3 for a week or two, only to see it fail in production?
Complexity is relevant, size is not Link to heading
Coming back to that original LinkedIn post. What is a “large change” anyway? I have submitted pull requests where I renamed a method in a thousand places. Yet, the change was low-risk since the code compiled.
The better question is, what is stopping you from shipping really small increments at a constant pace? I’m sure you will discover a lot of waste, such as slow CI, lacking git knowledge, QA gates, or long-lived branches.
Obligatory reference to Cunningham’s Law. ↩︎
The unit of “change”, in the case of the LinkedIn post, is a pull request. ↩︎
Pull request, change request, merge requests, changelist… ↩︎