official
spec-0007
Conventional Commits
Structured commit message format (type(scope): message) enabling automated changelogs and semver bumps.
| Version | 1.0.0 |
|---|---|
| Maturity | stable |
| Owner | w3dev |
| Updated | 2026-08-22 |
| Adopted | 2026-08-22 |
| Tags | gitworkflowtooling |
| Applies to | all |
| Related | semver, keep-a-changelog |
| Canonical URL | https://www.conventionalcommits.org/en/v1.0.0/ |
What it is
Conventional Commits is a lightweight convention for commit message structure:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
The type communicates intent at a glance — feat for a new feature, fix
for a bug fix, and so on. Because the format is machine-parseable, tooling
can walk a repository's commit history and derive a changelog and a semantic
version bump without a human summarizing anything by hand.
Why we adopted this
- Automated changelogs. Every release note comes straight from commit history instead of someone reconstructing "what changed" after the fact.
- Automated versioning.
fixcommits map to patch bumps,featcommits to minor bumps, and breaking changes to major bumps — semver stays consistent without a manual judgment call at release time. - Scannable history.
git log --onelinebecomes legible on its own; reviewers and future maintainers can tell what a commit does before opening the diff. - Low adoption cost. It's a message-format convention, not a new tool or process — it works with any git host and any CI system.
w3dev-specific notes
- Allowed types:
feat,fix,chore,docs,refactor,test,ci. Don't invent new types without updating this spec first. - Scope: in a monorepo, the scope is the package directory, e.g.
fix(api): handle empty request body. In a single-package repo, scope is optional and may be omitted. - Breaking changes: mark with a
!after the type/scope (feat(api)!: drop v1 endpoints) and include aBREAKING CHANGE:footer describing the migration. Both are required, not either/or.
Enforcement
- Commit messages are linted in CI on every pull request; a commit that doesn't parse as a Conventional Commit fails the check.
- Squash-merge commit titles must also follow the format, since that title
becomes the permanent commit message on
main. - Release tooling reads the merged history on
mainto generate changelogs and version bumps — non-conforming commits are excluded from the changelog and can cause a version bump to be missed.