Making the work tellable as one story.
A ticket ID in your branch name costs three seconds to type and saves hours of context-switching later. The convention is simple:
feature/PROJ-123-add-password-reset
fix/PROJ-456-null-pointer-in-export
chore/PROJ-789-upgrade-node-20
The ticket ID (PROJ-123) is the anchor. The slug after it (add-password-reset) is for humans reading git branch output. Together, they create a branch that's both searchable and scannable.
The same principle applies to commits. Including the ticket ID in the commit message — either in the subject line (fix(PROJ-456): handle null export payload) or in the body — lets you trace any line of code back to the work item that motivated it. git log --grep="PROJ-456" returns every commit related to that ticket, across every branch, instantly.
This traceability becomes critical during incident response. When a deploy breaks, you need to answer "what changed?" fast. If branches and commits reference ticket IDs, the path from "this commit broke production" to "here's the ticket with the full context" takes seconds. Without that link, you're reading diffs and guessing at intent.
The PR is where the code meets the ticket. A PR description that doesn't reference the ticket it implements is a missed connection — the reviewer sees what changed but not why, and the ticket sits in "in progress" until someone manually moves it.
Most platforms support keyword linking that automates this:
Closes #123
Fixes PROJ-456
Resolves #789
GitHub, GitLab, and Bitbucket all recognize these keywords in PR descriptions and will auto-link (and optionally auto-close) the referenced ticket when the PR merges. Linear and Jira support similar integration via branch names or PR descriptions. The cost is one line in your PR template. The benefit is end-to-end traceability from request to deploy.
A good PR description template is minimal:
Teams that consistently link PRs to tickets can answer "what shipped this week?" by querying their tracker instead of reading git log. The ticket becomes the single source of truth for a piece of work — from request through implementation to deploy.
Auto-close is the last link in the traceability chain: when a PR merges, the referenced ticket moves to "done" without anyone touching the tracker. It sounds minor. In practice, it eliminates an entire category of stale-ticket noise.
Without auto-close, tickets linger in "in progress" or "in review" long after the code has shipped. The board looks wrong. Sprint metrics are inaccurate. Engineers waste time manually dragging tickets to the done column — which they forget to do half the time, which means the board is always stale.
Setting it up depends on your stack. GitHub auto-closes tickets referenced with Closes #123 in the PR description by default — no configuration needed. Jira requires a GitHub (or Bitbucket or GitLab) integration that maps PR merges to workflow transitions. Linear handles it natively when PRs reference ticket IDs in the branch name.
The pattern is the same everywhere: reference the ticket in the PR, let the tooling handle the state change. One decision at PR-creation time saves a manual step on every merge and keeps your board honest.