A GitHub PR adds a collaboration layer on top of Git’s change graph. It is not just a screen with a merge button — it’s where change visibility, review decisions, and CI gating converge into a single unit.
Pull Request
A PR is a bundle of diffs between a source branch and a target branch. GitHub wraps that bundle with the metadata collaboration needs — review system, conversation threads, status checks, branch protection — and the result is what we call a PR.
flowchart LR
Open["PR opened
(diff bundle)"] --> Review["Review
(comment / approve / request changes)"]
Review --> Checks["CI status checks
(test / build / lint)"]
Checks --> Merge["merge"]
Merge --> Close["close"]
These four steps usually flow naturally, but a poor unit of design will jam one of them. The most common jam is at review time.
Designing PR-Sized Units
Small PRs get reviewed faster. The common rule of thumb is 200-400 lines of code, but more essential than the size is the principle of one intent per PR. Mixing a refactor with a new feature forces the reviewer to evaluate them separately, and as a result neither gets a thorough look.
Even big changes can stay single-intent when broken into stages. Adding a new interface, migrating call sites, removing the old interface — that kind of staged split keeps each PR small and each review light.
A draft PR is a tool for getting early feedback on unfinished work. You open the PR before it’s mergeable, gather opinions on the direction, and then continue the actual work. It’s especially useful as a checkpoint before committing to a large change.
The Code Review Cycle
Review isn’t just a venue for judging code right or wrong. Intent verification, knowledge sharing, and merge-readiness checks all happen there together.
Authors look at their own PR before requesting review. Reading your own change with the eyes of a first-time reader catches the small mistakes that often slip in just before merge — leftover debug code, unrelated edits, missing tests.
Reviewers pick one of four actions.
- comment: information, questions, suggestions
- suggestion: a small concrete change the author can apply directly
- request changes: something that must be addressed before merge
- approve: agreement that the PR can be merged
The core decision here is the blocker vs. nit distinction. Things that affect intent, correctness, or safety should be flagged as blockers; style or minor preference differences should be marked clearly as nits. When every comment carries the same weight, review gets heavier and real risks get buried among the noise.
After a reviewer leaves comments, the author either responds or makes the change and resolves the thread. Once enough threads are resolved, the PR reaches a mergeable state.
Merge Strategies
GitHub offers three options for merging a PR into main.
| Strategy | Graph Result | Trait |
|---|---|---|
| Merge commit | Branch-and-converge preserved | PR boundary remains visible in graph |
| Squash merge | Linear; one PR becomes one commit | Simple history, internal PR commits gone |
| Rebase merge | Linear; PR commits preserved as-is | Linear history, PR boundary blurred |
flowchart TB
subgraph Source ["Inside the PR"]
s1((c1)) --> s2((c2)) --> s3((c3))
end
subgraph MergeCommit ["merge commit"]
m1((m1)) --> m2((m2)) --> mc((merge))
m1 --> mc1((c1)) --> mc2((c2)) --> mc3((c3)) --> mc
end
subgraph Squash ["squash merge"]
sq1((m1)) --> sq2((m2)) --> sq3((squashed))
end
subgraph Rebase ["rebase merge"]
r1((m1)) --> r2((m2)) --> rc1((c1')) --> rc2((c2')) --> rc3((c3'))
end
The team convention is essentially a choice about main’s graph shape. If you want each PR to appear as one clean unit, squash merge is the simplest. If the commits inside a PR are meaningful steps (refactor → feature → cleanup), rebase merge preserves that flow. If the merge flow itself is valuable as a record of collaboration, merge commits are the natural choice.
Consistency matters more than the choice itself. A main branch that mixes squashes with merge commits ends up partly linear and partly branched in an awkward shape.
CI Gating and Branch Protection
PRs that merge on human review alone tend to leak regressions. Status checks are where automated verification belongs.
GitHub watches the result of every status check (test, build, lint) tied to the PR. A branch protection rule on main can require specific checks to pass before merge, which prevents a broken PR from reaching main even if a reviewer accidentally clicks merge.
Pairing this with required-reviewer counts, codeowner auto-assignment, and required-up-to-date-with-main settings closes most of the gaps that show up at the PR stage.
Common Pitfalls
Oversized PRs
A PR with thousands of lines gets reviewed in name only. The reviewer leaves an “overall LGTM” and real risks slide through. Big work needs to be split by intent for review to retain substance.
Bikeshedding
This is the pattern of spending review cycles on trivial preferences (indentation, name flavor) unrelated to the substance of the code. The cleanest fix is to remove these from review entirely by enforcing them with linters and formatters.
Auto-LGTM
When approval becomes a reflex, review becomes ceremony. A checklist (test coverage, intent change, security impact) or required multi-reviewer rules for large PRs are common safeguards that keep review honest.
Accumulating Merge Conflicts
The longer a PR stays open, the more it diverges from main, and the bigger the eventual conflict. Small PRs and fast reviews are the simplest answer; if that isn’t workable, frequent rebases against main keep the gap small.
Wrap-up
GitHub PRs add a unit of collaboration on top of the Git graph.
- PR unit: one intent, broken into small pieces
- Code Review: separate blockers from nits; authors review their own PRs first
- Merge strategy: stay consistent within team convention
- CI gating: tie automated checks to merge requirements via branch protection
In the end, a PR’s value comes from the combination of four pieces: unit design (one intent), Code Review (blocker / nit distinction), merge strategy (consistency), and the CI gate. If any one of them loosens, the PR gets stuck at the final step.
The next article digs into that automated verification itself — how GitHub Actions builds, tests, and deploys PRs.