Conventional Commits
debt(d3/e3/b3/t5)
Closest to 'default linter catches the common case' (d3). The term's detection_hints.tools list includes commitlint, semantic-release, and conventional-changelog — commitlint specifically runs as a git hook or CI step to catch non-conforming commit messages before they're merged. This is essentially a default linter for the commit convention.
Closest to 'simple parameterised fix' (e3). The quick_fix shows a straightforward format replacement: type(scope): description. Fixing non-conventional commits involves rewriting commit messages (git rebase -i for history, or just adopting the format going forward). It's more than a one-line patch since you may need to fix multiple commits or set up tooling, but it's a simple pattern adoption within one workflow.
Closest to 'localised tax' (b3). The convention applies to commit messages across the entire codebase, but it's a lightweight tax — every commit needs the format, yet it doesn't shape architecture or slow down code changes themselves. It's a persistent but minor overhead in the git workflow, not in the code structure.
Closest to 'notable trap' (t5). The misconception explicitly states that developers believe it's 'just a style preference with no functional benefit' when in fact tools parse commit types for automated versioning and changelogs. This is a documented gotcha — most devs eventually learn that feat→minor, fix→patch, BREAKING CHANGE→major, but initially many treat it as cosmetic and miss the automation benefits, leading to broken version bumps.
Also Known As
TL;DR
Explanation
Conventional Commits defines a structured format: <type>[optional scope]: <description>. Types: feat (new feature → bumps MINOR), fix (bug fix → bumps PATCH), docs, style, refactor, test, chore, perf. Breaking changes are indicated by a ! suffix or BREAKING CHANGE: footer (→ bumps MAJOR). Example: feat(auth): add OAuth2 login via GitHub. Tools built on this format: semantic-release (automated npm/GitHub releases), git-cliff and conventional-changelog (CHANGELOG generation), and commitlint (pre-commit enforcement). For PHP projects, use cocur/slug-based tooling or the standard semantic-release with a PHP adapter. Pair with a pre-commit hook (Husky or a PHP git hook library) to enforce the format.
Common Misconception
Why It Matters
Common Mistakes
- Inconsistent type prefixes across the team — some use 'feature:', others 'feat:', others nothing.
- Vague commit bodies: 'fix: bug' — the body should explain what was broken and how it was fixed.
- Not using BREAKING CHANGE footer for breaking API changes — automated tooling cannot detect them.
- Over-strict enforcement driving developers to make huge commits to avoid multiple messages.
Code Examples
# Non-conventional commits — no structure:
git log:
'fixed stuff'
'wip'
'FINAL'
'changes'
'more changes'
# Conventional commits:
'feat(auth): add OAuth2 Google login'
'fix(session): regenerate ID after privilege change'
'docs: add deployment runbook'
'feat!: rename user_name to username (BREAKING CHANGE)'
# Format: <type>(<scope>): <short description>
git commit -m 'feat(auth): add OAuth2 login via GitHub'
git commit -m 'fix(cart): prevent duplicate line items on concurrent add'
git commit -m 'refactor(payment): extract StripeGateway to adapter class'
git commit -m 'perf(query): add covering index on orders.user_id'
git commit -m 'docs(api): document /orders endpoint rate limits'
git commit -m 'test(checkout): add integration test for card decline flow'
git commit -m 'chore(deps): bump phpunit to 11.1'
# BREAKING CHANGE — add ! and footer:
git commit -m 'feat(api)!: rename /users to /members
BREAKING CHANGE: clients must update all /users references to /members'