Conventional commits without memorising the spec
Conventional Commits turn your git history into something tools can read — auto-generated changelogs and automatic semantic-version bumps — but only if every message follows the format precisely. This builder walks you through type, scope, subject, body, breaking changes, and issue references, then assembles a message that parses cleanly.
How it works
The output follows the type(scope): subject header rule. The type classifies the change (feat and fix drive minor and patch bumps; docs, refactor, chore and others document intent). An optional scope in parentheses names the affected area. The subject is your imperative one-liner. When you flag a breaking change, the builder appends ! to the header and adds a BREAKING CHANGE: footer — both recognised signals for a major-version bump. Issue numbers become a Closes #123 footer. A live counter checks the header length against the 50/72-character guidance so the first line stays readable in tools and git log.
The commit types and what they mean
| Type | SemVer impact | Use for |
|---|---|---|
feat | Minor bump | A new user-facing feature |
fix | Patch bump | A bug fix |
docs | None | Documentation changes only |
style | None | Formatting, whitespace — no logic change |
refactor | None | Code restructuring with no feature or fix |
perf | None | Performance improvements |
test | None | Adding or updating tests |
build | None | Build system or dependency changes |
ci | None | CI configuration changes |
chore | None | Maintenance tasks, tooling |
revert | Depends | Reverting a prior commit |
Breaking changes
A breaking change is any change that forces callers or users to update their code. Signal it two ways: add ! after the type/scope in the header, and add a BREAKING CHANGE: footer explaining what changed and how to migrate. Tools like semantic-release and standard-version treat either signal as a major-version bump.
For example:
feat(api)!: remove deprecated /v1/users endpoint
BREAKING CHANGE: /v1/users has been removed. Use /v2/users instead.
Closes #89
Complete example with body
fix(auth): retry token refresh on network timeout
The refresh step failed silently on flaky connections, logging users
out unnecessarily. Added exponential backoff with three attempts before
propagating the error.
Closes #234
The header is 51 characters — within the 72-character limit. The body explains the why rather than the what. The Closes footer links the commit to the issue tracker so the issue auto-closes on merge.
Tips
- Write the subject as a command: “add retry to upload”, not “added” or “adds”.
- Use a scope to disambiguate large repos:
fix(auth): handle expired refresh token. - Put the why in the body and the what in the diff — reviewers can already see the code change.
- For a reverting commit, choose the
reverttype and reference the original commit hash in the body. - Keep
chorefor true housekeeping only; if you upgraded a dependency to fix a security flaw, usefixso the patch release is tagged.