A code review is a human reading your change before it lands. It catches bugs the tests didn't think of, keeps designs consistent, spreads knowledge across the team, and gives newcomers the feedback loop they need to get good. Done well, it's the highest-leverage hour anyone spends on code. Done badly, it's where PRs go to die.
← Back to TestingWhat it isn't for: arguing about formatting (the formatter decides), catching style mistakes (the linter does), or ensuring tests exist (CI does). When tools take over the mechanical checks, review becomes about meaning.
| Tool | Style | Notes |
|---|---|---|
| GitHub Pull Requests | Branch-based, batch review | The default. Reviews entire branch as a single unit. |
| GitLab Merge Requests | Same idea | Similar feature set; integrated CI/CD. |
| Gerrit | Per-commit review | Each commit is reviewed separately, amend-and-rebase workflow. Common at Google, the LKML, OpenStack. |
| Phabricator (legacy) / Phorge | Per-diff review | Stacked diffs, tight pre-commit linting. Phorge is the community fork. |
| Graphite, Reviewable.io, CodeStream | Stacked / overlay tools | Add stacked-PR support and richer review UI on top of GitHub/GitLab. |
| Bitbucket, Azure Repos | Same idea, different UI | Common where the rest of the toolchain is Atlassian or Azure. |
The single biggest determinant of review quality. Studies (and every senior engineer's experience) show review effectiveness drops sharply past ~400 lines. Aim for <200 lines of meaningful diff. Bigger changes get rubber-stamped or sit for days.
How: stack PRs (refactor → feature flag → behavior → cleanup), feature-flag work in progress, separate refactors from feature changes.
Three sections, in order: What changed, why, and how to verify. Link to the issue, the design doc, or the bug. Screenshots for UI. The reviewer should know in 60 seconds whether to dive in or pass.
Read your own diff before requesting review. Half the embarrassing comments — debug print statements, commented-out code, leftover TODOs — get caught here.
A red CI is a "not ready for review" signal. Reviewers waste time on changes that the tools already say are broken.
Understand the goal before reading the code. Code that looks weird in isolation often makes sense once you know what it's solving — and code that looks fine sometimes solves the wrong problem.
"Why this approach instead of X?" beats "Use X." The author has context the reviewer doesn't. Asking surfaces it; demanding either steamrolls a good reason or invites a fight.
Use prefixes: nit: (cosmetic, optional), question: (curiosity, not blocking), blocking: (must fix before merge). The author knows what to act on without guessing.
If you find yourself commenting on indentation, quote style, or import order, the linter and formatter aren't doing their jobs. Fix them; reclaim review time for things humans need to think about.
Reviews older than ~24 hours grow stale; the author has moved on, context is lost, the rebase pile-up makes a small change feel like a saga. Treat review as a same-day commitment when reasonable.
If the change is good and a few minor things are not blocking, approve and leave the comments. "Approve with optional changes" is healthier than holding the PR for cosmetic improvements.
A file in the repo mapping paths to required reviewers. Changes to billing/ require a billing-team approval; changes to infra/ require infra. Auto-routes review requests; ensures critical paths get qualified eyes.
Block merge to main without: passing CI, at least one approval, no outstanding review-requested-changes. Most accidents happen in branches that bypass the rules.
If commit messages follow a convention (feat:, fix:, chore:), tools can generate changelogs and bump versions automatically. Conventional Commits, Changesets, release-please.
By 2026, AI review tools (CodeRabbit, GitHub Copilot Workspace, Cursor's review mode, Sourcegraph Cody) annotate PRs with summaries, surface likely bugs, and explain unfamiliar diffs. They speed up reviewers but don't replace them — final judgment still belongs to humans accountable for the code.