I have been writing code professionally for more than five years now. For the first four years, I never cared about the size of my pull requests (PRs). However, in the last year, I transitioned from submitting massive PRs with thousands of lines of changes to breaking them down into smaller, more manageable ones. The benefits of this shift have been immense, and in this blog, I’ll share those advantages.
According to GitHub, a pull request is:
A pull request is a proposal to merge a set of changes from one branch into another. In a pull request, collaborators can review and discuss the proposed set of changes before they integrate the changes into the main codebase.
Essentially, a pull request is a way of collaborating; we should do everything possible to enhance this collaboration. One effective method to improve this collaboration is to keep PRs small.
There is no universal definition to differentiate between a small and a large PR. Relying solely on the number of lines changed is insufficient, as auto-generated code and tests can inflate line counts. When I refer to small PRs in this article, I mean dividing a larger PR into multiple smaller, logically coherent PRs. Each smaller PR should be standalone, mergeable, and deployable.
I do not advocate artificial splitting like splitting a PR into two, one containing all the code and another with just the tests, as this approach fails to yield any benefits I share below.
Ask a programmer to review 10 lines of code, he’ll find 10 issues. Ask him to do 500 lines and he’ll say it looks good.
While humorous, this quote carries truth. Everyone is busy with their own work, and when you ask someone to review a PR, you are essentially requesting their time. Reviewing a PR requires the reviewer to switch context from their own work, and if the review takes a considerable amount of time, it can be challenging for them to return back to their work, potentially affecting their motivation and commitment to the review.
Smaller PRs, which only take about 20–30 minutes to review, are much easier to tackle compared to those that can take 2–3 hours. Plus, larger PRs often lead to oversights because our attention spans can only handle so much, and jumping between lots of changes in a single PR can be confusing. From my experience, smaller PRs tend to get better feedback and lead to more meaningful design conversations.
At this point, I’m thinking of adding my PR to my will in case it’s still in review after I’m gone.
Longer PRs require a significant time commitment from reviewers, making them less likely to get attention — especially if they’re not tied to high-impact features. Small PRs on the other hand are reviewed quickly, as they demand less of the reviewer’s time and are less intrusive.
This speed of reviews can be crucial for meeting project deadlines; I’ve seen projects getting delayed because senior reviewers couldn’t allocate time for massive PRs (though this can happen with small PRs, the risk is inherently higher with large ones).
Reworking a big PR after design changes is like rearranging deck chairs on a ship you just finished building… and then sinking it.
We have all experienced situations where someone realizes during PR review that a different design would have been more maintainable and future-proof, and we need to spend additional time reworking the PR based on the new design (not to say that they were completely on board with the design that was initially implemented :p). This is very natural because sometimes things become clearer once you see them written in code, and you start noticing aspects you might have missed during the design phase.
With large PRs, this can be a significant issue because you have to rework a lot of elements, but with smaller PRs, it is easier to make changes. More importantly, there is a lower chance of rework because reviewers are more likely to identify issues early on and address them in the initial PRs, allowing subsequent PRs to be based on the new designs.
Smaller PRs also benefit you as the author of the PR. They help in testing smaller changes incrementally rather than testing the whole project in one go. Testing smaller changes results in more exhaustive testing of each component of the system, thus leading to fewer production bugs. This applies to both automated tests and manual testing performed by you or dedicated QA engineers.
Moreover, smaller PRs reduce the likelihood of missed test cases, as you can focus on a limited scope rather than the entire system.
Writing tests? That sounds like Future Me’s problem.
I have seen developers (including myself in the past) hesitate to write automation tests due to the perceived time investment without immediate, “visible” value to the feature/product. Smaller PRs reduce this friction by limiting the number of tests required and the time spent writing them.
No matter how thorough your testing is, production bugs will happen! Being able to debug a bug in production is crucial since production bugs directly impact users, the business, or both. With large PRs, the surface area of change is also large, making it time-consuming and difficult to find the root cause of issues. On the other hand, smaller PRs contain less code and thus make debugging much faster.
Debugging small changes is like finding a typo; debugging big changes is like proofreading an encyclopedia.
Last but not least, smaller PRs are also helpful to your product manager and users. By using small PRs, you can continuously push parts of the system to production, which helps in obtaining early feedback from users and allows for early course corrections if needed.
Skipping early feedback is like cooking a five-course meal without tasting anything — you’re just hoping it’s not a disaster.
The benefits of small PRs are numerous, and the points outlined above are among the most impactful I’ve experienced personally. If you have encountered other advantages of small PRs or challenges with larger ones that I haven’t covered, do comment with your insights.
I hope this article motivates you to embrace smaller PRs. If you’re already on board, I hope it reinforces the value of this practice.
Thanks for reading, until next time, keep coding and stay curious!