Pull Request Size Best Practices
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
A good pull request contains one coherent change that a reviewer can understand and verify. I do not use a universal line-count rule because a generated client, rename, test fixture, and behavior change have very different review risk. I separate unrelated cleanup from the feature, explain why the change is needed, show how it was tested, and call out migration or rollout risk. If the work is large, I can land preparatory refactors, a disabled code path, and the final behavior in separate safe stages. The goal is that a reviewer can follow the contract, inspect the risky parts, and revert or deploy the change without untangling unrelated work.
Pull Request Size Best Practices
Direct Answer
A good pull request is small enough for a reviewer to understand as one coherent change. There is no universal line-count limit: generated files, tests, renames, and language affect the number. Split unrelated concerns, explain unavoidable size, and keep each commit/build in a useful state. Smaller focused diffs usually reduce review load and merge risk.
Code Example
// Large feature: Add order discount system (would be ~1200 lines)
// PR 1: Add database schema and entity (150 lines)
@Entity
public class Discount {
@Id
private Long id;
private String code;
private BigDecimal percentage;
private LocalDateTime expiresAt;
}
// PR 2: Add repository and basic service layer (200 lines)
@Service
public class DiscountService {
private final DiscountRepository repository;
public DiscountService(DiscountRepository repository) {
this.repository = repository;
}
public Optional<Discount> findByCode(String code) {
return repository.findByCode(code)
.filter(d -> d.getExpiresAt().isAfter(LocalDateTime.now()));
}
}
// PR 3: Integrate discount calculation into order flow (180 lines)
public BigDecimal calculateTotal(Order order, String discountCode) {
var subtotal = order.getItems().stream()
.map(Item::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
return discountService.findByCode(discountCode)
.map(d -> subtotal.multiply(BigDecimal.ONE.subtract(d.getPercentage())))
.orElse(subtotal);
}
// PR 4: Add REST endpoint behind a feature flag (120 lines)
Each PR leaves the codebase compiling and is independently reviewable.
Common Mistakes & Pitfalls
- Using a universal line limit: changed-line count is a signal, not a measure of correctness or risk.
- Mixing unrelated work: formatting, refactoring, and behavior changes compete for the reviewer's attention.
- Splitting by file instead of behavior: fragments may be harder to understand and test than one coherent change.
- Creating unsafe intermediate states: schema and application changes need a compatible deployment order.
- Hiding unavoidable size: call out generated files, migrations, risky paths, tests, and rollout details.
Check your understanding
Answer these without looking back at the article.
- What is a feature flag and how does it enable continuous integration?
- How do you handle breaking a large refactor into small PRs without breaking the build?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.