What Makes a Good Pull Request Description (6 Templates)
The description's job is to direct the reviewer's attention, not restate the diff. Six copy-paste templates, sized to the change, grounded in 2,896 measured PRs.
Published:
Last Updated:
Direct answer
A pull request description has one job: tell the reviewer where to look and what you are unsure about. The reviewer can read the diff. They cannot read your intent, your rejected alternatives, or your doubt. Template weight should scale with change size - across 2,896 merged PRs we measured on 2026-10-18 the median was 63 lines across 3 files, but 52% of PRs over 1,000 lines got zero inline comments.
What makes a good pull request description?
Direct answer: It supplies the three things a diff cannot: why this change exists now, which parts carry risk, and what the author is unsure about. Everything else is restatement. The test is whether a reviewer knows where to spend attention before opening the Files Changed tab. Measured against 2,896 merged PRs, 2026-10-18.
Almost every guide to this topic is a list of sections. Summary, motivation, type of change, screenshots, checklist. Those lists are not wrong, they are just answering the wrong question. The question is not what sections should a description have. It is what information does the reviewer not already have.
The reviewer has the diff. They have the file list, the line counts, the commit messages, the CI status, the linked issue if you linked it, and in most repos an AI reviewer’s auto-generated summary sitting in the first comment. Restating any of that is work you did for nobody.
Here is what they do not have, and cannot get:
| Information | In the diff? | Who can supply it | Why the reviewer needs it |
|---|---|---|---|
| What the code now does | Yes | Nobody needs to | Reviewer reads it in seconds |
| Which files changed | Yes | Nobody needs to | GitHub renders it |
| Why this change, why now | No | Author only | Decides whether to approve the intent at all |
| Alternatives you rejected | No | Author only | Stops the reviewer proposing the thing you already tried |
| The constraint that forced an ugly shape | No | Author only | Prevents a style objection to a load-bearing hack |
| Which hunks are mechanical | No | Author only | Lets the reviewer skim 400 lines and focus on 40 |
| What you are unsure about | No | Author only | Directs the single most valuable minute of review |
| How you verified it | Partly | Author | Sets the reviewer’s trust level for the rest |
| Blast radius and rollback | No | Author only | Determines how hard they look |
That table is the article. Four of the nine rows are available from no other source in the universe, and three more are available only at real cost to the reviewer. A description that covers those seven rows in 60 words beats a 400-word one that covers the first two beautifully.
The single highest-leverage sentence you can write is the one most people omit: “I am not confident about the retry logic in backoff.go lines 40 to 70, please look hardest there.” That sentence converts a diffuse scan into a targeted review. It is also socially expensive to write, which is why people do not write it, and why teams that normalise it get better reviews than teams that do not.
The second-highest-leverage sentence is the reading order. On anything over roughly 300 lines, “read schema.sql first, then migrate.go, the rest is call-site updates” saves the reviewer the ten minutes they would otherwise spend building that map themselves.
The restatement trap
The reason this needs saying is that the default behaviour, for both humans and machines, is restatement. Ask a tired engineer at 6pm to fill in a Summary box and they will write what the code does, because that is the easiest true thing to write. Ask a model to generate a description from a patch and it will do the same, because the patch is all it has. Both outputs are correct and both are close to worthless, for the same reason: the reviewer is about to read the patch anyway.
Judgement: if your description could have been generated from the diff alone, it should have been, and then you still owe the reviewer the part that could not.
Template weight should scale with pull request size
Nobody says this, and the data makes it obvious.
We measured 2,896 human-authored merged pull requests across 10 major public repositories, created between 17 Apr and 17 Oct 2026, with 104 bot authors removed. Full method and percentiles are in how big should a pull request be. Two findings from that dataset set the template policy.
Finding one: the median pull request is tiny. 63 changed lines across 3 files. p75 is 205 lines, 74.3% of all pull requests are under 200 lines. A nine-section template with a rollout plan, a screenshot slot and a twelve-item checklist is being applied, in the overwhelming majority of cases, to a 63-line change. That is not rigour, it is tax. And it is a tax with a perverse effect: when the form is obviously oversized for the change, authors learn to clear it with one keystroke, and the habit carries over to the PR where the form mattered.
Finding two: on big pull requests the description is doing all the work. In the same dataset, inline review threads per 100 changed lines fell from 1.55 for pull requests under 50 lines to 0.085 for pull requests over 1,000 lines - an 18-fold drop in scrutiny density. 52% of merged pull requests over 1,000 lines carried zero inline review comments. Not one. On those PRs, whatever understanding the reviewer formed came from the title, the description, and a scroll.
An honest counterweight, from the same analysis: absolute comment counts do rise with size (Spearman rho +0.355). Big changes are not ignored. They are reviewed far less per line. Either way, the marginal value of description effort is highest exactly where effort is currently lowest.
So the policy writes itself:
| PR size (changed lines) | Share of our sample | Description that is correct | Why |
|---|---|---|---|
| Under 50 | 46.4% of PRs under 200 lines sit here | Title plus one sentence plus ticket link | Reviewer reads the whole diff faster than your paragraph |
| 50 to 199 | Remainder of the 74.3% under 200 | Minimal template: what, why, how tested | Enough to frame intent, not enough to be tax |
| 200 to 999 | Roughly the p75 to p90 band | Standard template plus a reviewer-guidance line | Reviewer needs a route through it |
| 1,000 and over | p90 is 628, p99 is 4,584 | Full treatment: reading order, mechanical-versus-judgement split, rollback | 52% of these get zero inline comments |
Per-repo spread matters too, and kills any universal rule: pandas ships 96.9% of its pull requests under 200 lines, VS Code only 57.4%. Set your bands from your own distribution. More on thresholds in pull request size best practices.
The six templates
Copy these directly. They are plain Markdown and go straight into .github/pull_request_template.md or a file inside .github/PULL_REQUEST_TEMPLATE/.
Two conventions used throughout. HTML comments are instructions to the author and should be deleted before submitting - a linter can flag leftovers. And every checklist item is something a machine cannot verify, because anything a machine can verify belongs in CI.
1. Minimal (use this as your default)
This is the one that fits the median 63-line pull request. If you adopt exactly one template, adopt this one.
## What and why
<!-- One sentence on the change. One on why now. -->
## Reviewer notes
<!-- Where to look first. Anything you are unsure about. Delete if genuinely trivial. -->
Closes #
Three prompts, roughly 20 seconds to complete, and the second one is the box that carries all the value. Do not add a Type of Change radio list to this. GitHub labels already carry that, and a checkbox the author ticks is worse data than a label the team can filter on.
2. Standard feature
## Summary
<!-- What this adds, in one or two sentences. -->
## Why now
<!-- The trigger: ticket, incident, customer, deadline, dependency. -->
## Approach and alternatives
<!-- How you built it, and what you considered and rejected. This is the box
that stops a reviewer from proposing the thing you already tried. -->
## How I verified this
<!-- Commands run, cases covered, screenshots or a short clip for UI. -->
## Reviewer guidance
<!-- Read X first. Y and Z are mechanical. I am unsure about W. -->
## Risk and rollback
- [ ] Behind a feature flag, OR safe to revert with a plain revert commit
- [ ] No irreversible data change
- [ ] Monitoring or alerting covers the new path
Closes #
3. Bug fix
The root-cause box is the most valuable field in any template in this article. It is the only place where the knowledge of why the system allowed this gets written down, and it is the field most often left empty.
## The bug
<!-- Observable symptom. Link the issue, incident, or Sentry event. -->
## Root cause
<!-- Why the system allowed this. Not "missing null check" - why was it missing? -->
## The fix
<!-- What changed, and why this fix rather than a broader one. -->
## Blast radius
<!-- What else touches this code path? What did you check was unaffected? -->
## Regression guard
- [ ] Added a test that fails without this fix (paste the failing output)
- [ ] Reproduced the original bug and confirmed it no longer occurs
- [ ] Checked whether the same pattern exists elsewhere in the codebase
Fixes #
4. Refactor or codemod
Refactors are where line counts lie hardest. A 3,000-line codemod can be safer than a 40-line hand edit, and the description is the only thing that tells the reviewer which one they are looking at.
## Behaviour change
- [ ] None. This is a pure refactor.
<!-- If any behaviour changes, stop and describe it here in full. -->
## Motivation
<!-- What becomes possible or cheaper after this lands. -->
## Mechanical vs judgement
<!-- Which paths were generated or find-and-replaced, and which were
hand-written. The reviewer should skim the first and read the second. -->
Generated or mechanical:
Hand-written, needs real review:
## How I know behaviour is unchanged
<!-- Test suite unchanged and green? Codemod script included? Diff of
compiled output? Snapshot comparison? Be specific. -->
## Tooling
<!-- Paste the codemod, script or IDE operation used, so it can be re-run. -->
5. Migration or schema change
The only template here that deserves to be long, because the failure mode is irreversible.
## What changes in the schema
<!-- Tables, columns, indexes, constraints. Before and after. -->
## Deploy order
<!-- Does code ship before migration, after, or simultaneously?
Name the exact sequence. This is the question that causes incidents. -->
1.
2.
3.
## Backward compatibility
- [ ] Old application code keeps working against the new schema
- [ ] New application code keeps working against the old schema
- [ ] If neither, the deploy order above is mandatory and stated
## Data volume and lock risk
<!-- Row count of the affected table. Expected duration. Does it take a
lock? Is it online? Tested against a production-sized copy? -->
## Rollback plan
<!-- Not the word "revert". The actual steps, including what happens to
rows written between deploy and rollback. -->
## Verification
- [ ] Ran forward migration against a production-shaped dataset
- [ ] Ran the rollback against the same dataset
- [ ] Confirmed no full table scan or long-held lock
6. Dependency bump
Usually automated, usually rubber-stamped, occasionally a supply-chain incident. The template’s job is to force a two-minute look at the diff of the dependency, not the diff of the lockfile.
## Package and versions
<!-- name: old -> new. Direct or transitive? -->
## Why
- [ ] Security advisory (link the CVE or GHSA)
- [ ] Required by another upgrade
- [ ] Routine maintenance
## Breaking changes in the changelog
<!-- Paste the relevant lines, or write "none, reviewed changelog for
versions X through Y". Do not leave this blank on a major bump. -->
## What I checked
- [ ] Read the release notes between the two versions
- [ ] Checked whether maintainership or ownership of the package changed
- [ ] Build and full test suite pass
- [ ] Lockfile diff contains no unexpected additional packages
That last item is the one that catches real attacks, and no CI job runs it for you by default.
How to write a pull request template
Direct answer: Put a single default at
.github/pull_request_template.md. For change-specific variants, add aPULL_REQUEST_TEMPLATE/directory inside.github, the repo root ordocs, one Markdown file per type, selected with the?template=query parameter on the compare URL. Verified against GitHub’s documentation 2026-10-18.
File locations GitHub checks, verified at GitHub’s own docs on 2026-10-18:
pull_request_template.mdin the repository root.github/pull_request_template.md- the tidiest and by far the most commondocs/pull_request_template.md
The filename is case-insensitive. Commit it to the default branch and it applies to the next pull request opened.
Multiple templates live in a PULL_REQUEST_TEMPLATE subdirectory, which GitHub accepts in all three of the same parent locations. Contributors select one on the compare URL:
https://github.com/acme/api/compare/main...my-branch?expand=1&template=bugfix.md
Two practical notes most guides miss. First, the directory does not give you a default - if you only create .github/PULL_REQUEST_TEMPLATE/*.md, a contributor who opens a PR the normal way gets an empty box. Keep a default file alongside the directory. Second, nobody types that URL by hand. The selection only happens in practice if something constructs the link: a bot comment on a new branch, a gh pr create --template wrapper, or an issue-template action that links out. If you build the directory and then do not build the path to it, you have built six templates that get used zero times.
Other hosts, for completeness: GitLab uses .gitlab/merge_request_templates/*.md and exposes a dropdown natively, which makes multi-template selection genuinely usable there in a way it is not on GitHub. Azure DevOps uses .azuredevops/pull_request_template/. Bitbucket has its own equivalent.
What belongs in the template, and what belongs in CONTRIBUTING.md
This is the cleanest decision rule in the article:
| Question | Where it goes | Reason |
|---|---|---|
| What changed and why | Template | Different every time |
| How you tested this change | Template | Different every time |
| What the reviewer should look at | Template | Different every time |
| Rollback plan for this change | Template | Different every time |
| Branch naming convention | CONTRIBUTING.md | Identical every time |
| Commit message format | CONTRIBUTING.md | Identical every time |
| How to run the test suite locally | CONTRIBUTING.md | Identical every time |
| DCO, CLA, code of conduct | CONTRIBUTING.md | Identical every time |
| Who reviews what | CODEOWNERS | Enforced, not requested |
| Lint, format, type check, coverage | CI | A machine can check it |
If the answer is the same on every pull request, it is documentation, not a prompt. Link it from one line at the bottom of the template. The reason this matters is not tidiness - it is that stable rules bulk out the template, bulk makes authors delete the block wholesale, and the per-change prompts die with it.
Equally: every checklist item a CI job can verify should be deleted from the template and made a required check. A human ticking “tests pass” is strictly worse than a status check, because it is unverified and it consumes attention that should have gone to “I confirmed this migration is reversible.”
Enforcement
GitHub pre-fills a template. It never requires anyone to complete it. Two mechanisms actually hold:
- A required status check that parses the pull request body and fails when required headings are empty or placeholder comments survive, wired into branch protection. One gotcha that bites teams using a merge queue: GitHub’s
merge_groupevent is separate frompull_requestandpush. If your body-check job triggers only onpull_request, the merge queue stalls permanently, because, per GitHub’s documentation, status checks “will not be triggered… The merge will fail as the required status check will not be reported.” Addmerge_groupto the trigger list. - An AI reviewer configured to read the template as intent and comment when the diff drifts from the stated scope. CodeRabbit accepts custom review instructions in natural language, which can include checking that a named section is filled in.
Our earlier, lighter treatment of the file mechanics is at how to write a pull request template; this page supersedes it on strategy and template design.
What should our team include in pull request reviews?
Direct answer: Three things from the author - intent, risk, and uncertainty - and three from the reviewer: does the diff match the stated intent, is there a test that fails without the change, and is the rollback real. Everything mechanical belongs in CI. Keep the human checklist to items a machine cannot verify.
Reviews fail in two directions and the fixes are different.
Failure one: the review never starts. This is the bigger problem by volume. In our second dataset, 2,189 human-authored merged pull requests across 12 repositories, the median pull request spends 52.7% of its open-to-merge life waiting for the first human to look at it. Open to first review is 8.7h at p50, 66h at p75, 212h at p90. Once someone starts, it moves: first review to merge is 6.7h at p50, and first approval to merge is 1.1h. Full breakdown in pull request review time.
A description does not fix assignment latency, but it changes who picks the PR up. “Touches the billing webhook, 40 lines, need someone who knows idempotency keys” gets claimed faster than “updates webhook handler.”
Failure two: the review starts and is shallow. That is the 18-fold scrutiny-density drop, and it is what reviewer guidance is for.
A review checklist worth keeping is short, and it is a reviewer checklist, not an author one:
| Check | Why it is on a human list |
|---|---|
| Can I say what this does in one sentence? | If not, the description failed and the review will be shallow |
| Does the diff match the stated intent? | Scope creep is invisible to CI and expensive later |
| Is there a test that fails without this change? | Coverage percentage does not answer this |
| What happens on the unhappy path? | Error handling is the most common real defect class |
| Is the rollback story real? | ”Revert it” is not a plan once data has been written |
| Did the author flag uncertainty, and did I address it? | The one question they asked for is the one most often skipped |
Note what is absent: formatting, import order, naming consistency, line length, and anything a linter owns. Those are the comments that make reviews feel productive while adding nothing, and they crowd out the six rows above. We have a longer treatment in code review checklist and code review best practices.
One structural number worth knowing when you design the process: 59.2% of merged pull requests in our sample had exactly one approver, 14.5% had two, mean 1.08. Two-reviewer policies are far rarer in practice than in policy documents. If you are deciding, see how many reviewers a pull request needs.
Auto-generated descriptions: who writes them, and the honest limitation
Direct answer: CodeRabbit, Qodo Merge, PR-Agent, cubic, Graphite and What The Diff all generate pull request descriptions from the diff. That is the limitation, not a feature gap: a generated description restates the diff, which is precisely the part the reviewer did not need. Generate the walkthrough, write the intent yourself. Verified 2026-10-18.
Here is the market, with what each one actually produces:
| Tool | Generates description | Mechanism | What it cannot supply |
|---|---|---|---|
| CodeRabbit | Yes, automatically on PR open | Summary plus a file-by-file walkthrough table, posted as the first comment | Why now, rejected alternatives, author uncertainty |
| Qodo (Qodo Merge) | Yes, on demand | The /describe command rewrites title, type and description | Same |
| PR-Agent | Yes, on demand | /describe, self-hosted, MIT since 23 April 2026, bring your own key | Same |
| cubic | Yes | Generated summary alongside review comments | Same |
| Graphite | Yes | Description generation plus org-wide automation rules | Same |
| What The Diff | Yes, that is the whole product | Diff-to-prose summary | Same |
Every row of the right-hand column is identical, and that is the finding. A generator has exactly one input: the patch. It can tell you that retryWithBackoff was added to client.go and that three call sites were updated. It cannot tell you that you tried a token bucket first and abandoned it because the upstream rate limiter is per-tenant, or that you are unsure whether the jitter is correct. Nothing in the patch encodes that.
So the generated summary is competing with the diff, which the reviewer is about to read anyway, in a format the reviewer trusts less. It is not useless - on a 40-file change, a walkthrough table is a genuine navigational aid, and the title and type normalisation keeps your PR list scannable. But it is structurally incapable of producing the part of the description that has any information content.
The practical pattern we would run:
- Let the tool generate the summary and the walkthrough. Accept that it is restatement and let it be.
- Write two to four sentences yourself, above the generated block, covering why now, what to look at, and what you are unsure about.
- Never delete step 2 because step 1 made the box look full. That is the actual risk of auto-generation: a full-looking description that contains no information suppresses the one that would have.
If you have a bot writing descriptions, make sure your template still renders above the bot’s comment, and that the reviewer-guidance box is visibly empty when the author skipped it. Empty and obvious beats auto-filled and hollow.
What a good description does for an AI reviewer
Several tools read more than the diff, and the description is part of that context. This is documented, and the write-capable versus read-only split is sharper than most comparisons admit. Verified against vendor documentation 2026-10-18:
| Tool | Reads linked issue as context | Can write back to the tracker |
|---|---|---|
| CodeRabbit | Yes, Jira and Linear documented | Yes - chat.integrations.jira.usage can create issues |
| Semgrep | Yes | Yes - auto-creates Jira tickets, severity-gated, Jira Cloud only |
| Snyk | Yes | Yes - manual button plus two API endpoints |
| PR-Agent | Yes | No |
| Qodo Merge | Yes | No |
| GitHub Copilot | Yes | No |
| Graphite | Yes | No |
| Anthropic Code Review | Yes | No |
| Cursor Bugbot | No integration documented | No |
Only three of the nine are write-capable. Semgrep is the only vendor honest enough to document the negative, stating that it “does not support bi-directional or two-way status syncing.” And no product in the market routes individual findings by CODEOWNERS, which remains a genuine gap.
Now the part where we decline to make the claim you might expect. It is intuitive that a description stating intent improves what an AI reviewer returns, and we believe it does. But no published study measures it, and we are not going to invent a percentage. What we can tell you is that there is evidence pulling in the opposite direction on volume: SWE-PRBench, an independent benchmark of 350 human-annotated pull requests, found that frontier model detection performance degrades as context grows - an attention-dilution effect. Indexing and retrieval is not the same thing as stuffing more tokens into a prompt, but the finding still argues for a tight, specific description over a thorough one.
So the operational advice is: a short intent statement naming the risky function is a better bet than three paragraphs of background. If you are configuring tools, note that the most powerful context channels are not the description at all - they are the rule files. Anthropic Code Review reads REVIEW.md from the base branch, never from the PR’s own diff, so a pull request cannot alter its own review rules. CodeRabbit’s knowledge_base.code_guidelines.filePatterns defaults include **/REVIEW.md, **/CLAUDE.md, **/AGENTS.md, **/.cursorrules and .github/copilot-instructions.md, which means it reads its competitors’ rule files by default. More on this in AI pull request review and how to automate code review.
One caution worth repeating wherever AI review comes up: no party without a commercial stake has published a false-positive rate, precision figure or noise measurement for any shipping commercial AI code reviewer. Anthropic publishes under 1% false positives with 84% bug detection on pull requests over 1,000 lines; that is a vendor’s own unreplicated figure and should be treated as such. If you are choosing on cost as well as quality, our price-first analysis is at the cheapest AI code review tools that are still worth running.
How we verified this
Our own data. Two datasets harvested from the GitHub GraphQL API on 2026-10-18, both ours and both published with method:
- PR size and scrutiny: 2,896 human-authored merged pull requests, 10 repositories, 104 bot authors removed, created 17 Apr to 17 Oct 2026. Median 63 changed lines across 3 files; p75 205; p90 628; p99 4,584; 74.3% under 200 lines. Inline threads per 100 changed lines 1.55 under 50 lines versus 0.085 above 1,000. 52% of merged pull requests over 1,000 lines had zero inline review comments. Counterweight: Spearman rho between size and absolute comment count is +0.355. Published in how big should a pull request be.
- Review latency: 2,189 human-authored merged pull requests, 12 repositories, bot authors and reviewers and self-reviews excluded. Open to first review p50 8.7h, p75 66h, p90 212h. Median PR spends 52.7% of open-to-merge life waiting for a first human. 59.2% had exactly one approver. Published in pull request review time. Disclosed limit: only merged pull requests are in frame, which biases latency downward.
Primary sources we fetched on 2026-10-18. GitHub’s pull request template documentation, for the three valid file locations, the PULL_REQUEST_TEMPLATE subdirectory in all three parents, and the template query parameter. GitHub’s merge queue documentation for the merge_group status-check behaviour and the quoted failure text. CodeRabbit’s pricing page for plan names and linked-repository caps.
What we could not verify, stated plainly:
- No published measurement exists of how much a human-written pull request description improves AI review output. We looked. We are not estimating one.
- We could not find a vendor that publishes a measured quality delta between a generated description and an author-written one. The limitation we describe is structural (the generator’s only input is the patch) rather than benchmarked.
- GitHub’s documentation does not state whether the
PULL_REQUEST_TEMPLATEdirectory name is case-sensitive; it consistently uses uppercase, so we use uppercase. - Adoption rates for pull request templates across public repositories are not something we measured in this dataset, and we have not seen a credible published figure. We make no claim about how common templates are.
- Per-language or per-repository variation in description quality is unmeasured, here and everywhere.
Known conflict disclosure. Where this cluster of articles cites the c-CRAB benchmark (arXiv 2603.23448), note that five of its six authors are academic but Ridwan Shariffdeen lists SonarSource as his affiliation, and Sonar acquired Gitar on 21 May 2026. Gitar is a paid sponsor of this site. SonarQube is not among the four tools c-CRAB evaluates, which blunts the conflict, and the paper carries its own disclaimer. We disclose it anyway because we call out vendor-funded benchmarks everywhere else.
Recommendations
Stated criteria: lowest author cost that still redirects reviewer attention, and no checklist item a machine could verify.
If you adopt one thing, adopt the minimal template. Three prompts, .github/pull_request_template.md, under 20 seconds. It fits the 74.3% of pull requests under 200 lines, which is the only reason it will survive contact with a tired engineer on a Friday.
Add the reviewer-guidance line to every template you own. “Read X first, Y is mechanical, I am unsure about Z.” It is one line, it is the highest-value line, and it is the first thing people cut.
Build the directory only if you will build the path to it. .github/PULL_REQUEST_TEMPLATE/ with ?template= works, but nothing surfaces it. If you are not going to add a gh pr create wrapper or a bot link, keep one default template and put the variants in your wiki as copy-paste blocks instead.
Put the migration template behind a required check. Of the six here, the migration template is the only one where an unfilled box reliably costs money. Make deploy order and rollback plan required sections, fail the build when they are empty, and add merge_group to the trigger list so your merge queue does not deadlock.
Let a tool write the summary, write the intent yourself. If you already run CodeRabbit, Qodo, cubic or self-hosted PR-Agent, take the generated walkthrough and keep your two sentences above it. The generated block is navigational; your two sentences are informational. Do not let a full-looking box talk you out of the only part that mattered.
Scale effort by size, not by policy. One sentence under 200 lines. Reading order plus a mechanical-versus-judgement split over 1,000. More than half of those big pull requests get zero inline comments, so the description is the review.
Further reading
- How Big Should a Pull Request Be? What the Data Says
- Pull Request Review Time: What We Measured
- How to Write a Pull Request Template
- Code Review Checklist for Authors and Reviewers
- Pull Request Review Best Practices
- The Complete GitHub Pull Request Review Guide
- Draft Pull Request vs Pull Request
- The Cheapest AI Code Review Tools That Are Still Worth Running
GitarComments are not enough
Gitar applies the fix, validates it in CI, and clears the queue.
See it on your repo Read our independent Gitar reviewFrequently Asked Questions
Pull request review checklist for developers
A reviewer checklist works best when it only holds items a machine cannot check. Ours is five questions. One, can I state what this change does in one sentence after reading the description? Two, does the stated intent match the diff, or did scope creep in? Three, are the risky paths identified, and did the author say what they are unsure about? Four, is there a test that fails without this change? Five, is the rollback story real, or is it the word revert? Lint, formatting, type checks and coverage thresholds belong in CI, not on a human list. Every item you automate buys attention back for the four questions above.
AI code review best practices for pull requests
Four rules hold up. First, keep pull requests small, because scrutiny density collapses with size. In our 2,896-PR measurement taken 2026-10-18, inline review threads per 100 changed lines fell from 1.55 under 50 lines to 0.085 above 1,000 lines. Second, write the intent down, because tools that read the description and linked issue are working from your framing, not from the diff alone. Third, never let an AI review satisfy a required approval unless you have decided that deliberately. GitHub Copilot can be configured to submit an approving review, which is off by default. Fourth, measure noise. No party without a commercial stake has published a false-positive rate for any shipping commercial AI reviewer, so you have to measure your own.
How do AI code review tools fit into a pull request workflow?
Most attach as a GitHub App or CI job that fires on pull request open and subsequent pushes, posting a summary plus inline comments within a few minutes. The useful mental model is that they are a first-pass filter running before the human, not a replacement for one. Anthropic Code Review, generally available 15 Oct 2026, never approves or blocks. GitHub Copilot can approve if an admin turns it on. Cursor Bugbot runs per push or once per PR depending on triggers.frequency in .cursor/config/bugbot.yaml. The integration decision that matters most is whether the tool is a required status check, because a required check that does not fire on the merge_group event will deadlock a GitHub merge queue permanently.
What makes a good pull request description?
Three things the diff cannot supply: why the change exists now, which parts carry risk, and what the author is unsure about. Everything else is restatement. A reviewer can read the diff in a few seconds; what they cannot read is the alternative you rejected, the constraint that forced an ugly shape, or the one function you want a second opinion on. The practical test is whether a reviewer who skims the description knows where to spend their attention before they open the Files Changed tab. If the description does not redirect attention, it did nothing. Length should scale with the change: one line is correct for the median 63-line pull request.
How do I set up multiple pull request templates on GitHub?
Create a PULL_REQUEST_TEMPLATE directory inside .github, the repository root, or docs, and add one Markdown file per change type, such as feature.md, bugfix.md and migration.md. Contributors select one by appending the template query parameter to the compare URL, for example compare/main...my-branch?template=bugfix.md and optionally expand=1. Verified against GitHub's own documentation on 2026-10-18. Keep a lightweight default at .github/pull_request_template.md for everything else, because the directory alone does not give you a default. Do not build eight of them. Selection friction is real, and a template nobody picks is worse than no template, since it signals a process that is not actually running.
Should I let an AI tool write my pull request description?
For the summary section, yes. For the intent section, no, and this is the limitation nobody states plainly. CodeRabbit, Qodo Merge, PR-Agent, cubic, Graphite and What The Diff all generate descriptions from the diff, which means the generated text restates the diff. That is exactly the part the reviewer did not need, because they are about to read the diff. The generator cannot know why you chose this approach, which alternative you discarded, or which function you are unsure about, because none of that is in the patch. Use generation for the walkthrough and file inventory, then write two sentences of intent yourself. Those two sentences are the whole value.
What belongs in a pull request template versus CONTRIBUTING.md?
The template holds per-change information that differs every time: what changed, why now, how it was tested, what to look at. CONTRIBUTING.md holds stable rules that are identical across every pull request: branch naming, commit conventions, how to run the test suite, the code of conduct, the DCO or CLA requirement, release cadence. The test is simple. If the answer is the same on every pull request, it is documentation and it belongs in CONTRIBUTING.md with a one-line link from the template. Putting stable rules in the template trains authors to delete the whole block, which takes the per-change prompts down with it.
How long should a pull request description be?
Scale it to the change. Across 2,896 human-authored merged pull requests measured 2026-10-18, the median was 63 changed lines across 3 files, and 74.3% were under 200 lines, so most descriptions are covering a small focused change where one sentence plus a ticket link is complete. The case for effort is at the other end: 52% of merged pull requests over 1,000 lines in that sample carried zero inline review comments. On those, the description is doing nearly all of the reviewer-guidance work, and a file-by-file reading order plus an explicit list of what is mechanical versus what needs judgement is worth ten minutes of the author's time.
Do pull request descriptions improve AI code review quality?
Probably, but no published measurement exists and we will not invent one. What is documented is that several tools ingest the description and linked issue as context. CodeRabbit documents Jira and Linear integrations and reads issue context; Qodo Merge and PR-Agent read linked issues read-only; Cursor Bugbot documents no issue-tracker integration at all, verified 2026-10-18. There is a counterweight worth knowing: SWE-PRBench, the independent benchmark at arXiv 2603.26130, found that frontier model detection performance degrades as context grows, an attention-dilution effect. So a tight description stating intent is a better bet than a long one stating everything.
Explore More
Free Newsletter
Stay ahead with AI dev tools
Weekly insights on AI code review, static analysis, and developer productivity. No spam, unsubscribe anytime.
Join developers getting weekly AI tool insights.
Related Articles
How to Setup CodeRabbit: Complete Step-by-Step Guide (2026)
Set up CodeRabbit for AI code review in under 10 minutes. GitHub App install, .coderabbit.yaml config, review profiles, and troubleshooting all covered.
February 28, 2026
how-toAI Code Review in GitHub Actions - Setup Guide
Add AI code review to GitHub Actions. Covers CodeRabbit, PR-Agent, Semgrep, and SonarQube integration with production-ready YAML config examples.
February 9, 2026
how-toHow to Use ChatGPT for Code Review (with Prompts)
Use ChatGPT for code review with proven prompt templates for security, performance, and readability. Includes GitHub Actions integration and cost analysis.
February 13, 2026
CodeRabbit Review
Qodo Review
Cubic Review
Graphite Review