PR templates, bulk review suggestions, linked issues, label automation, stacked PRs, PR size discipline, the GitHub CLI for daily PR work, and the metrics that tell you whether your review process is actually working
A PR template pre-fills the description field when a PR is opened. A good template reduces reviewer confusion, cuts back-and-forth, and encodes your team's "definition of ready" directly into the PR workflow.
Create .github/PULL_REQUEST_TEMPLATE.md — it auto-fills every new PR description.
Create a directory .github/PULL_REQUEST_TEMPLATE/ with multiple .md files. GitHub does not auto-select one — the author appends a query param to the PR URL to choose:
Automate the URL selection in your branch naming conventions — a branch named hotfix/* could be linked from your runbook to the hotfix-template URL.
The .github/ISSUE_TEMPLATE/config.yml file controls what happens when a user clicks "New issue." You can disable blank issues (forcing a template choice) and add external links for support or security reports:
bug_report.yml) over Markdown ones (bug_report.md). YAML templates render as structured forms with required fields, dropdowns, and checkboxes — they're much harder for reporters to skip past than a free-text Markdown template.
GitHub's review interface has several features that senior reviewers under-use. Knowing them makes reviews both faster and more actionable.
In the diff view, click the + next to a line, then click the "Insert a suggestion" icon (or use the keyboard shortcut while writing the comment). The suggestion renders as an inline diff the author can apply with one click — no back-and-forth explaining what to type.
When a reviewer leaves multiple suggestions across a PR, the author can apply all of them in a single commit:
This keeps the commit history clean instead of producing one micro-commit per suggestion.
| State | What it signals | Blocks merge? |
|---|---|---|
| Comment | Feedback without an explicit verdict — questions, suggestions, observations | No |
| Approve | The reviewer is happy for this to merge (subject to other requirements) | No — enables merge |
| Request changes | The reviewer has blocking concerns that must be addressed before merge | Yes — counts as a required dismissal until addressed and re-reviewed |
block: or issue: comments is ambiguous — does the author need to address them before merging? Use "Request changes" for anything that must be fixed. Use "Approve" only when you're genuinely satisfied. This is a cultural norm to establish explicitly.
Review threads can be marked "Resolved" by the PR author once addressed. But resolved threads are hidden by default — reviewers who want to verify fixes must click "Show resolved" to re-examine them. Two practices help:
GitHub's closing keywords let a PR automatically close one or more issues when it merges. This keeps issue trackers tidy without manual cleanup.
The issue closes only when the PR merges to the default branch. Merging to a non-default branch (e.g. release/v2.4) does not trigger the close.
When a PR is linked to an issue (via closing keyword or manual link in the sidebar), and the issue is in a GitHub Project, you can automate status transitions:
Set this up under your Project's Settings → Workflows. It gives you a lightweight Kanban board that stays accurate automatically — no manual status updates needed.
Fixes org/product-tracker#42. The PR in the code repo will display the linked issue and close it on merge.
Labels are only useful if they're applied consistently. Manual labelling drifts — automate it.
The actions/labeler action reads a config file and applies labels based on which files changed in a PR:
| Category | Labels | Purpose |
|---|---|---|
| Area | area/payments, area/auth, area/frontend | Route notifications to the right team; filter PR dashboards by domain |
| Type | bug, feature, refactor, docs, dependencies | Changelog generation; sprint categorisation |
| Size | size/xs, size/s, size/m, size/l, size/xl | Review SLA enforcement; flag oversized PRs |
| Status | blocked, needs-review, on-hold, ready-to-merge | Triage and queue management |
| Priority | priority/critical, priority/high, priority/low | On-call severity; release scheduling |
| Backport | backport release/v2.4 | Trigger the backport action (Phase 3) |
EndBug/label-sync action against a .github/labels.yml source of truth in your .github org repo. Run it on a schedule or on push to propagate label changes to all repos in the org automatically.
A stacked PR (also called a "PR stack" or "dependent PR chain") is a series of PRs where each one targets the previous branch rather than main directly. The stack is merged bottom-up — the base PR merges first, then each layer re-targets main and merges in turn.
A large feature often has natural layers: data model changes, service logic, API layer, UI. Shipping them as one 1,500-line PR makes review nearly impossible. Stacking lets you ship each layer independently while continuing work on the layers above.
| Tool | What it automates | Notes |
|---|---|---|
| Graphite (graphite.dev) | Full stack management: create, update, rebase, merge; web dashboard; Slack notifications | SaaS, free tier available; most polished UX; GitHub integration via GitHub App |
| spr (github.com/ejoffe/spr) | CLI: stacks PRs from individual commits on a single branch; auto-rebases stack when base merges | Open source; commit-based stacking (different philosophy from branch stacking) |
| gh-stack | gh extension: visualises and manages branch-based stacks | Lightweight; no external service; manual rebase required |
| Benefit | Cost |
|---|---|
| Reviewers see focused, smaller diffs | If the base PR needs significant changes, all dependent PRs need rebasing |
| Unblocks development — work continues while reviews happen | Complex to manage without tooling; easy to lose track of stack state |
| Smaller PRs merge faster; feedback loop is tighter | Requires discipline: each layer must be independently deployable or feature-flagged |
Research consistently shows that PR review quality degrades sharply above ~400 lines of diff. Reviewers shift from finding bugs to pattern-matching for shape, and approve without truly understanding the change.
These are change lines (git diff --stat additions + deletions), not file count. A PR touching 20 files but changing 3 lines each is fine. A PR touching one file with 600 changes needs splitting.
| Situation | How to split |
|---|---|
| Feature with schema + logic + UI | Stack three PRs (see 4.5): schema first, then service, then UI |
| Refactor + new feature mixed together | PR 1: pure refactor (no behaviour change). PR 2: new feature on top of the clean code. Easier to review both. |
| Large test file additions | Acceptable to have tests in a follow-up PR if the implementation PR is already large — but link them explicitly |
| Dependency update + dependent code change | PR 1: dependency bump. PR 2: code changes that use the new API. The first is trivially reviewable. |
| Config/infra change + application change | Always separate — different reviewers, different risk profiles |
We covered branch protection settings in Phase 3. Here we focus on the review-specific behaviours that trips teams up in practice.
When enabled, any new commit pushed to the PR after an approval dismisses all approvals — the reviewer must re-approve. This is the correct default for production branches: an approval on commit A is not an approval on commit A + B.
The only time to disable this: late-stage PRs where only trivial changes (typos, rebase commits) are expected. In that case, ask the reviewer to explicitly re-approve rather than disabling the protection globally.
When CODEOWNERS references a team (e.g. @acme/payments-team), GitHub requires at least one member of that team to approve — not just any reviewer. If the PR touches files owned by two teams, one approval from each team is required.
By default, anyone with write access can dismiss a pull request review. Use "Restrict who can dismiss pull request reviews" to limit this to specific users or teams. This prevents:
Additional approvals beyond the minimum required count still appear in the PR — they're visible social signal even though they're not mechanically required. Encourage reviewers who aren't CODEOWNERS to still leave substantive approvals or comments. Their input has value even if the system doesn't require it for merge.
The gh CLI brings GitHub's PR workflow into the terminal. Senior developers who live in the terminal find it dramatically faster than context-switching to the browser for routine PR operations.
You can't improve what you don't measure. These are the metrics that actually predict team velocity and code quality — not lines written or PRs merged per day.
The most important flow metric. High cycle time means long-lived branches, integration risk, and slow feedback. Target: <2 days for most teams.
Measures reviewer responsiveness. Long TFR kills momentum and encourages developers to context-switch away, forgetting the PR. Target: <4 hours.
1–2 rounds is healthy. 5+ rounds indicates unclear requirements, PR too large, or a reviewer/author communication problem.
Use median to ignore outliers. If your median is creeping above 300, your review quality is degrading even if nobody notices.
Metrics tools can't measure review quality directly, but these proxy signals are reliable:
| Signal | What it suggests |
|---|---|
| High approval rate with zero comments | Rubber-stamping — reviews aren't substantive. Either PRs are too small and trivial, or reviewers are approving without reading. |
| All comments are nits/style | Reviewers are focusing on surface rather than logic — consider automated formatting to free reviewer attention for substance. |
| Bugs found post-merge that were visible in the diff | Review quality problem — reviewers may be overwhelmed or PRs may be too large to review properly. |
| Long review threads that could have been a conversation | Missing async communication norms — a 15-comment thread on a design question should have been a 5-minute Slack discussion first. |
| PRs approved quickly by a single reviewer every time | Review load is concentrated — bus factor risk and likely rubber-stamping under time pressure. |