Conventional Commits
Format all commit messages according to the Conventional Commits 1.0.0 specification at https://www.conventionalcommits.org/
Ensures consistent, semantic commit messages that support automated changelog generation and semantic versioning.
Commit Message Format
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Type Reference
| Type | When to Use | SemVer | | ---------------- | ------------------------------------ | ------ | | โจ feat | New feature | MINOR | | ๐ fix | Bug fix | PATCH | | ๐ docs | Documentation only | - | | ๐จ style | Formatting, whitespace (no code) | - | | โป๏ธ refactor | Code restructuring (no feature/fix) | - | | โก๏ธ perf | Performance improvement | - | | โ test | Adding/fixing tests | - | | ๐๏ธ build | Build system, dependencies | - | | ๐ท ci | CI/CD configuration | - | | ๐งโ๐ป chore | Maintenance, tooling | - | | โฎ๏ธ revert | Reverting previous commit | - |
Decision Framework
When determining commit type, ask:
- New functionality? โ
feat - Bug fix? โ
fix - Documentation only? โ
docs - Performance improvement? โ
perf - Code restructuring without behavior change? โ
refactor - Code style/formatting only? โ
style - Tests added/modified? โ
test - Build system or dependencies changed? โ
build - CI/CD configuration changed? โ
ci - Maintenance or tooling? โ
chore
Message Best Practices
Description (first line)
- Keep under 50 characters
- Use imperative mood ("add" not "added")
- Don't capitalize first letter
- No period at end
Scope
Use clear, consistent names: feat(auth):, fix(api):,
docs(readme):
Body
- Include when change requires explanation
- Explain why the change was made
- Describe what problem it solves
- Wrap at 72 characters per line
Footers
Fixes #123- Reference issuesCo-authored-by: Name <email>- Credit contributorsBREAKING CHANGE: description- Breaking changesRefs: #456, #789- Related issues
Breaking Changes
Indicate breaking changes using either method:
feat!: remove deprecated API endpoint
feat(api)!: change authentication flow
fix: update validation logic
BREAKING CHANGE: validation now rejects empty strings
Command Execution
Using Jujutsu (Recommended)
jj describe -m 'feat(auth): add OAuth2 support'
For multi-line messages:
jj describe << 'EOF'
feat(auth): add OAuth2 support
Implement OAuth2 authentication flow with support for
Google and GitHub providers.
BREAKING CHANGE: removes legacy session-based auth
EOF
Using Git (Alternative)
Use single quotes to avoid shell escaping with !:
# Correct - single quotes
git commit -m 'feat!: add new authentication flow'
# Incorrect - DO NOT USE
git commit -m "feat\!: add new authentication flow"
For multi-line messages, use HEREDOC:
git commit -m "$(cat <<'EOF'
feat(auth): add OAuth2 support
Implement OAuth2 authentication flow with support for
Google and GitHub providers.
BREAKING CHANGE: removes legacy session-based auth
EOF
)"
Workflow
Using Jujutsu (Recommended)
- Make your code changes
- Run
jj statusto see what changed - Determine type using decision framework
- Use
jj describeto set commit message - Run
jj show @ --no-patchto verify
# Check changes
jj diff
# Set message
jj describe -m 'feat(api): add rate limiting to endpoints'
# Verify
jj show @ --no-patch
Using Git (Alternative)
- Stage changes:
git addfirst if nothing staged - Review changes:
git diff --cached - Check recent style:
git log --oneline -5 - Determine type using decision framework
- Execute commit with single quotes
- Verify:
git log -1
# Check for staged changes
git diff --cached --stat
# If nothing staged, stage first
git add .
# Review changes
git diff --cached
# Check recent style
git log --oneline -5
# Commit
git commit -m 'feat(api): add rate limiting to endpoints'
# Verify
git log -1
Quality Checks
Before committing, verify:
- [ ] Message accurately describes the changes
- [ ] Type correctly categorizes the change
- [ ] Scope (if used) is meaningful and consistent
- [ ] Breaking changes are properly marked with
!or footer - [ ] Description is clear and under 50 characters
- [ ] Body wraps at 72 characters (if present)
Examples
Simple fix:
fix: prevent null pointer in user lookup
Feature with scope:
feat(api): add rate limiting to endpoints
With body:
refactor: extract validation into separate module
Move validation logic from controllers to dedicated
validator classes for better testability and reuse.
Breaking change:
feat!: upgrade to v2 API format
BREAKING CHANGE: response structure changed from
{data: [...]} to {items: [...], meta: {...}}
With issue reference:
fix(auth): resolve token refresh race condition
Fixes #234
Full Specification
For complete specification details, see references/full-spec.md.
For practical patterns and common workflows, see
references/common-patterns.md.