Pull Request

Artifact

A request to merge a set of changes into the main line, holding the explanation, the review, and the automated checks that happen before the merge.

Why it exists

Code gets changed on a branch split off from the main line — a separate line of work — and at some point that work has to go back in. With no procedure at that moment, two things vanish: the chance for someone else to look before it lands, and any record of why the change was made that way.

Theo worked like that in Pagedeck's early days, merging straight into the main line as soon as he was done. It was fast, and two days later a saving bug appeared and took a day to track down. The cause was one deleted line of exception handling, and there was nowhere to ask why it had been deleted. The history held the change itself; the reasoning behind it lived only in Theo's memory, which is not a place anyone else can search.

A pull request creates a place before the merge. You ask for the change to be merged while writing down what you changed and why, attaching automated check results, and collecting a colleague's comments. That place survives the merge. Six months later, someone reading the same code can trace their way back to it.

What goes in it

Five things. A person writes the first two; tools fill the last three.

  1. Title — one line saying what was done. Someone scanning a list should be able to guess the change from the title alone. A title reading only "fix" or "improve" tells a list reader nothing, and the list is where most people meet the request.
  2. Description — why it was changed, what changed, and how it was verified. Why matters most. What changed is visible in the code; why this approach was chosen over another disappears unless it's written here. Linking the related work item or support ticket carries the background along too, so the next reader doesn't have to reconstruct it.
  3. The changes — which lines in which files differ, displayed automatically. What needs managing here is size. Past about 400 changed lines, review is known to turn formal: the reader can't hold attention, so they flag whatever stands out and move on. The number of comments per line falls as the request grows.
  4. Automated check results — unit test and linter output gets attached. A unit test isolates one function or module to verify it; a linter catches rule violations automatically. It's where a tool filters out everything a human shouldn't have to look at, leaving the reviewer the parts only a person can judge.
  5. Reviewers and merge conditions — who has to look, and what has to be satisfied before merging. Fix the conditions in advance, like checks passing plus one approval, and nobody negotiates them per merge. Conditions decided case by case get decided by whoever is in a hurry.

The draft state gets used too. When you only want to ask whether the direction is right, you open it half-finished, collect comments, and convert it to a full review later. Nobody is expected to read it line by line in that state.

Who writes it and who reads it

The developer who changed the code writes it. The description takes five minutes and saves the reader thirty. The gap between two people explaining the same change shows up right there, and it compounds across a hundred requests a quarter.

Four groups read it.

  1. The reviewer is the first reader. Code review — a colleague examining the code before it merges — is the activity, and it happens in this place.
  2. Automation reads it before any human does. With continuous integration in place — merging often and verifying automatically — checks run the moment the request opens and the results get attached. A failing check usually means nobody needs to read the code yet.
  3. Whoever reads that code later. When they wonder why something is the way it is, they find the request that line arrived in and read the description and the discussion. In practice this use earns as much as the review does, and it lasts far longer.
  4. Whoever watches delivery reads the list. A pile of requests open for a long time signals that the merge step is blocked, usually because reviewers are the bottleneck rather than the authors.

A request left open is itself a cost. While the main line keeps changing, staying split increases merge conflicts — the state where the same place was changed two different ways and can't be combined automatically.

How it sounds at work

"This request is 1,200 lines. Split it into two or three."

It's too large to review properly.

"The description doesn't say why. I can't judge this from the code alone."

Asking for the reasoning behind the change.

"Opened as a draft. Just check the direction for now."

A marker that comments are wanted before it's finished.

After that saving bug, Pagedeck blocked direct merges to the main line and routed everything through requests. When Theo opened a change deleting the same exception handling again, he wrote in the description why he judged the line unnecessary. In review, another developer pointed out that the premise behind that judgment only held under certain conditions.

Because that exchange stayed on the request, a similar ticket four months later didn't reopen the same discussion. It took twenty minutes instead of a day, and most of those twenty minutes were spent finding the request.

What people get wrong

The most common belief is that you only open one when the code is finished. It's a place to be reviewed, so a finished product feels like the right thing to submit. But it delays the moment you learn the direction was wrong. Hear that the approach was mistaken after three days of work and those three days are gone. Opening a draft to check direction first shrinks that risk to a few hours. Left in place, the finished-only habit grows the requests, and large requests make review formal again.

The other common belief is that bundling changes together is more efficient, since opening a request and getting it reviewed carries a cost each time. But review time doesn't rise in proportion to size — past a point it drops sharply instead. A request over 400 lines usually gets skimmed, and problems from a skimmed request surface after the merge, where fixing them costs far more. Splitting raises the number of reviews while shortening each one, and the total comes down. Two hundred lines twice beats four hundred once.

Easily confused with

TermWhat it isHow it differs
Code reviewA colleague examining code before it mergesAn activity, where a pull request is the place that activity happens and the request itself. You can review side by side with no request, and a request can be merged with nobody reviewing it. Treat them as one thing and an opened request gets mistaken for a finished review

Where to go next

Last updated 2026-09-16