engineering-handbook/commit-messages.md

5.1 KiB

Commit Messages

Adapted from commit-messages-guide by Romulo Oliveira, licensed under CC-BY-4.0.

Sea Haven uses Conventional Commits for every commit and PR title. A structured type(scope): description header keeps history scannable, drives tooling (changelogs, release tagging, PR-title linting), and maps cleanly onto SemVer.

Format

type(scope): description
  • type (required): the category of change, from the Types table below.
  • scope (optional): the area of the codebase affected, in parentheses and lowercase (auth, api, parser, deps). Omit it when the change is broad or no single scope fits.
  • description (required): a short summary in imperative mood, lowercase, with no trailing period.

Examples:

feat(parser): add retry logic for transient upstream failures
fix(auth): correct null check in session handler
docs: document the CI-on-merge workflow
chore(deps): bump aws-cdk-lib to 2.150.0

Types

Type Use for
feat A new feature or capability
fix A bug fix
docs Documentation only
style Formatting or whitespace with no behavior change
refactor A code change that neither fixes a bug nor adds a feature
perf A change that improves performance
test Adding or correcting tests
build Build system, packaging, or dependency changes
ci CI/CD configuration and workflows
chore Routine maintenance that doesn't touch source or tests
revert Reverting a previous commit
release Cutting a release (version bump, tag, changelog)

Rules

Keep the header short

Keep the whole header (type, scope, and description) under 72 characters, and aim to keep the description itself around 50. The header is for scanning; details go in the body.

Use imperative mood in the description

Write what the commit does, not what you did.

Good Bad
feat: add retry logic to payment processor feat: added retry logic to payment processor
fix: correct null check in auth handler fix: fixed null check in auth handler
refactor: remove deprecated endpoint refactor: removing deprecated endpoint

Lowercase the description, no trailing period

The type carries the emphasis, so the description stays lowercase and unpunctuated.

Good Bad
fix: correct null check in auth handler fix: Correct null check in auth handler.

Explain "why," not "what"

The diff shows what changed. The body should explain why.

Good Bad
perf: increase timeout to handle slow upstream responses perf: change timeout from 30 to 60
build: switch to arm64 to reduce Lambda cold start cost build: update architecture setting

No generic descriptions

A valid type does not excuse a vague description. These are not acceptable:

  • fix: stuff
  • chore: update code
  • chore: misc changes
  • chore: address review comments

Every commit should describe a specific change. WIP commits do not belong on shared branches.

No self-referential language

Good Bad
fix: correct race condition in queue processor fix: this commit fixes a race condition
feat: add input validation for email field feat: this PR adds validation
refactor: simplify auth middleware for clarity refactor: I refactored the auth middleware

Breaking changes

Mark a breaking change with a ! before the colon, and add a BREAKING CHANGE: footer describing the migration. Breaking changes drive a SemVer MAJOR bump (see Versioning).

feat(api)!: remove the deprecated /v1/receipts endpoint

BREAKING CHANGE: clients must migrate to /v2/receipts. The v1
response shape is no longer returned.

Template

type(scope): description (header under 72 chars, imperative, lowercase)

Optional body wrapped at 72 characters. Explain the problem
this commit solves and why this approach was chosen. Mention
side effects or non-obvious consequences.

Refs: PROJ-123, #123

Referencing issues

Use the Refs: trailer to point at the work this commit relates to:

  • Jira key (DEV-123, PLAT-7, SEC-4) when the work tracks a Jira issue. The GitHub for Jira app reads the key and threads the commit into the issue's development panel. See git-workflow.md.
  • GitHub issue (#123) for repos where GitHub Issues are enabled (contractor and fork repos only).

The Jira key is required in the PR title suffix (KEY-123). Including it in the Refs: trailer of each commit is recommended but not required — the link forms as long as the key appears in the PR title.

Example

feat(payments): add retry logic for transient upstream failures

The payment processor occasionally returns 503 during
deployments. Without retries, these surface as user-facing
errors. This adds exponential backoff with 3 attempts,
which matches the upstream's documented recovery window.

Refs: PROJ-123