Skip to main content
The PR title becomes a commit subject the moment it merges. Write it like a commit, because it is one. Pull requests are the unit of change that lands on the repo’s integration branch: develop on git-flow repos, main on trunk-flow repos. See Branch conventions → Which model applies to check which one a given repo uses. The title, the description, and the merge strategy together decide what the changelog says. They also decide how easily someone six months from now can answer “why did this happen?”

Title

  • Use the same conventional-commit prefix the squash commit uses. feat: …, fix: …, chore(scope): …. The squash-merge takes the PR title as the commit subject verbatim; if the prefix is wrong, release-please computes the wrong version bump.
  • No emoji. Same rule as commit subjects: machine-parsed surface, no decoration.
  • Under 70 characters. Lengthy context belongs in the body, not the subject line that GitHub truncates in the merged-PR list.
  • Imperative mood, present tense: “add netflow firewall rule,” not “added” or “adding.”
  • Scope is optional, lowercase, in parens when used: feat(api): rate-limit token refresh.

Body

Three sections, in this order:
  1. ## Summary: 1–3 bullets covering why this change exists. Not the diff (the reader sees that); the motivation. If the PR closes a Linear issue or GitHub issue, say so here (Closes JAC-50, Fixes #127).
  2. ## Test plan: bulleted markdown checklist. What CI runs automatically (bun run build, pnpm test, tofu fmt -check), and what a reviewer still has to verify by hand (browser smoke test, reviewed Terrakube plan, anything CI cannot see). Tick the boxes as work completes.
  3. Optional: ## Security notes: when the change touches credentials, IAM scopes, network exposure, or anything else where the security review is non-obvious from the diff. Empty section = “I considered it and there is nothing to flag” (different from “I did not think about security”).
Lead with the why. The diff already shows the what. PR descriptions that just restate the diff in English are dead text. The reader skims past them straight to the files.

Merge strategy

Trunk-flow repos (no develop)

  • Squash-merge is the default. One PR = one commit on main. The PR title becomes the commit subject; the PR description becomes the commit body. release-please walks this linear history to compute version bumps.
  • Any merge method is allowed. Squash is the default; merge and rebase are fine when the history is worth keeping. The merge button pre-fills the PR title as the subject, so it already passes the commit-message rule.
  • No force-push to main. Force-push to your own feature branch is fine while the PR is open.

git-flow repos (has develop)

  • PRs target develop by default. Squash is the only method on develop, enforced by a ruleset: one PR, one commit on develop.
  • develop → main promotion is merge-commit only, enforced by a ruleset. Squash and rebase into main are banned, no exceptions. The release-please release PR is not a main PR: it targets develop, squash-merges there, and the promotion carries it to main.
  • hotfix/* is the one exception to PR targeting. It branches from main, its PR targets main directly with a merge commit (never squash), and a second PR from the hotfix branch (not from main) carries the fix into develop.
  • No force-push to main or develop. Force-push to your own feature branch is fine while the PR is open.

Review

  • CI must be green before merge. CodeQL alerts must be resolved, not dismissed.
  • A reviewer’s request changes blocks merge until the author addresses every comment, either with a fix or with a written reply explaining why no fix is needed. Silent dismissal is not acceptable.
  • The author drives the conversation. If a reviewer goes quiet for more than 24 h on an open PR, the author pings them in the PR thread or on Slack. The PR stops waiting silently.

Tone in the description and review thread

  • Tell hard truths directly. Don’t soften with “perhaps” or “maybe consider.” Disagree explicitly when you disagree.
  • ALL CAPS from the requester means refocus immediately. A capitalized correction is the highest-priority signal in the conversation; everything else pauses until that direction is followed.
  • Explain complex reasoning. A two-line diff with five lines of justification is fine; an ambiguous diff with no rationale is not.

What this connects to

Commit conventions

The vocabulary the PR title uses. Subject rules, tone, autonomy: all the same.

Branch conventions

Branch type predicts the PR title prefix. One decision, made once.

Git transport

Why private-repo PR pushes go over HTTPS even when public repos use SSH.

CI/CD policy

The release-please flow that consumes the squash-commit subject.