How Stacked PRs Improve Code Review Quality?

Introduction

When there’s a change of only 10 lines, one can carefully check the comments; with 10000 lines, everything is LGTM (Looks Good to Me)!

Recently, I’ve noticed that the energy for code review is limited, possibly due to the lack of confidence from insufficient testing coverage, or the code being hard to understand and maintain, and possibly due to factors like being on leave. In any case, to concentrate well on reviewing thousands of lines of code changes is itself quite a challenge. As the one submitting the code, is there a way to improve the review efficiency? Perhaps we can try Stacked PRs.

Splitting Code Changes for Better Review (PRs)

Various studies and experiences indicate that too long or too many code reviews can reduce efficiency🔗, so it is best to break down large PRs into independent and more understandable changes. However, sometimes the changes are interdependent and can block progress.

For example, a complex feature might involve database adjustments, business logic modifications, UI changes, and even rewrites of documentation or tests. If all changes are packed into a single PR for review, it can significantly increase the review difficulty.

At this point, we can use the technique of Stacked PRs to break down large features into a series of smaller PRs, each with a clear purpose and based on the previous PR, ultimately turning a complex branch into manageable multiple branches for review.

mainfeature/dbfeature/business-logicfeature/uifeature/testBasePR1: Create schemaPR2: Favorite APIPR3: Frontend UIPR4: Integration testmerge PR4merge PR3merge PR2merge PR1 into main

Details of Stacked PR Practice

  1. The earliest PR opened is reviewed first.
  2. All PRs are treated as Work in Progress (WIP) status; even after review, they cannot be merged yet.
  3. Only after the most recently created PR has been fully reviewed can the merges begin in a sequential manner from the last created PR.

Stacked PR is Just a Means

Stacked PRs also bring maintenance burdens, the most obvious issue being the synchronization of progress between branches. Whether using merge or rebase, it brings additional operational overhead, which is one of the problems many tools aim to address:

While I prefer the concept of Trunk Based Development🔗: “branches that exist for long periods should be avoided as much as possible,” by frequently pushing updates to the main branch for development, it’s also good to understand another perspective in solving problems.

Further Reading