Commit Messages and PR Descriptions That Help Everyone

Good commit messages and pull request descriptions are the cheapest documentation you will ever write. They explain why a change exists at the exact moment someone needs the answer. Done well, they make reviews faster, debugging calmer, and onboarding less painful. Done badly, they slow everything down and hide landmines for the next person. This post is a practical guide you can hand to a team and use today.

What a great commit message looks like

Aim for small, focused commits that each do one thing. Then describe that one thing clearly.

Shape

  • A short subject line in the imperative: Add, Fix, Refactor
  • Wrap the body to short lines so humans can read it in terminals and tools
  • Explain the why before the how
  • Call out side effects, trade offs, and user visible changes
  • Reference issues or links at the end

Examples

Good, plain style:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    Refactor exposure calculation to use median

    The previous approach used a rolling average which lagged during sudden
    brightness changes. Median is more robust to outliers from car headlights
    and plane trails.

    Benchmark on two nights showed a 17% reduction in overexposed frames.
    No config changes required.

    Refs: #241
    ```

    Good, conventional style with a scoped subject:

    ```bash
    fix(capture): handle empty sensor frame gracefully

    When the sensor returns an empty buffer the loop now skips the frame,
    logs at warn level, and continues. Previously this raised and halted
    the observation.

    Adds a test for empty buffer.

    Closes: #322

Bad:

1
    misc tweaks

Why that hurts: there is no search term for future you, no reason, and no scope. Reviewers and archeologists will waste time opening the diff to guess what happened.

Checklist for a single commit

  • Does the subject read like a command
  • Does the body explain why this change is needed
  • Would someone in six months understand the trade offs
  • Is there a link or issue reference if one exists
  • Could you split this into two clearer commits

A commit template you can drop in

Commit templates turn good habits into defaults. Save this as .gitmessage and point Git at it:

1
    git config --global commit.template ~/.gitmessage

Template:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Short summary in the imperative (keep it concise)

Why:
Explain the problem this solves or the goal it achieves.

What:
Describe the approach at a high level. Mention alternatives you rejected if useful.

Impact:
Risks, user visible changes, config or data migrations, performance notes.

Refs:
Issue numbers, docs, or links that add context.

What a great pull request description looks like

A pull request description should let a reviewer answer three questions fast: what changed, why it changed, and how to verify it. Keep it structured and predictable so readers do not hunt for the basics.

PR structure

  • Title mirrors the commit subject of the primary change
  • Summary in one or two sentences on the intent
  • Details that explain what changed and why that approach was chosen
  • Before and after with screenshots, logs, or a short code sample
  • How to test with exact steps, commands, and test data
  • Risks and rollback with a short plan to back out safely
  • Related links to issues, specs, or previous PRs

Example PR body

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Summary
Switch capture loop to median based exposure calculation to resist outliers.

Details
- Replace rolling average with O(1) median estimator
- Add unit tests for spike and dropout cases
- Wire new metric to dashboard "exposure robustness"

Before / After
- Night 1: 14 overexposed frames -> 3
- Night 2: 11 overexposed frames -> 2

How to test
1) Run test suite: make test
2) Replay fixtures: tools/replay.sh fixtures/night-2024-10-12
3) Confirm dashboard shows the new metric

Risks and rollback
- Median estimator could underreact to slow drifts
- Rollback: revert commit abc123 and redeploy

Related
- Issue #241
- Design note: docs/exposure-metrics.md

A PR template you can commit

Create .github/pull_request_template.md:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
## Summary

## Details

## Before / After

## How to test

## Risks and rollback

## Related

Templates do not lock you in. They guarantee the basics show up and make reviews consistent.

Team habits that keep quality high

  • Prefer small PRs. A small, coherent change with a sharp description is easier to review than a grab bag
  • Match message and scope. If the message needs a comma, the commit may need a split
  • Update the PR description when the code changes. Keep the story in sync as you iterate
  • Link to the why. If there is an issue, benchmark, or doc that explains the decision, include it
  • Use labels to triage by type, component, or risk
  • Protect main with a passing build and at least one review
  • Adopt a linter only if it helps. Tools like commitlint enforce a style, but the content still has to be useful

What bad commit messages do to a project

  • Slow reviews because reviewers have to decode intent instead of checking correctness
  • Hide context so future maintainers cannot tell whether a strange decision was deliberate or accidental
  • Break search. Fix stuff does not match any error message or component name when you are grepping for clues
  • Kill release notes. You cannot auto generate a meaningful changelog from vague subjects
  • Waste time during incidents. In an outage you need to scan history fast. Empty messages force costly diff reading
  • Nudge the wrong culture. If seniors accept junk messages, others will follow and the codebase will feel hostile to newcomers

When to squash and when to keep history

  • Squash before merge if the branch has lots of noisy fix lint or oops typo commits. Preserve a single, well written message that tells the story
  • Keep a series when each commit is a logical step that stands alone and helps bisect later. Give each one a clear message

A lightweight workflow you can copy

  1. Write the change in small steps
  2. Use the commit template to record intent as you go
  3. Open a PR with the template sections filled
  4. As feedback lands, keep the PR description current
  5. Before merging, squash noise or split if scope crept
  6. Merge with a message that would help a stranger

Quick reference

Good subject verbs: add, remove, fix, rename, document, refactor, revert, optimise, configure, upgrade, pin
Avoid: tweak, stuff, changes, WIP
Always include: why the change exists, what it affects, and how to verify it
Sometimes include: performance numbers, links, screenshots, migration notes

Great messages and PRs take a minute longer to write and save hours later. They make the work easier for reviewers, for future you, and for the person who joins next month and has to change this code without breaking anything.

Thanks for reading.


↤ Previous Post