@gfmio/config-commitlint
v1.0.1
Published
Shared commitlint configuration used across many projects
Readme
@gfmio/config-commitlint
Shared commitlint configuration for enforcing consistent, meaningful commit messages across projects using the Conventional Commits specification.
Installation
npm install --save-dev @gfmio/config-commitlint @commitlint/cli @commitlint/config-conventional @ngx-devs/commitlint-plugin-imperativeyarn add --dev @gfmio/config-commitlint @commitlint/cli @commitlint/config-conventional @ngx-devs/commitlint-plugin-imperativepnpm add --save-dev @gfmio/config-commitlint @commitlint/cli @commitlint/config-conventional @ngx-devs/commitlint-plugin-imperativebun add --dev @gfmio/config-commitlint @commitlint/cli @commitlint/config-conventional @ngx-devs/commitlint-plugin-imperativeUsage
Create a commitlint.config.js file in your project root:
export default {
extends: ['@gfmio/config-commitlint/commitlint.config.ts']
};Or use a .commitlintrc.json file:
{
"extends": ["@gfmio/config-commitlint/commitlint.config.ts"]
}That's it! The shared configuration will be applied to your commit messages.
Extending the Configuration
You can override or extend any rules from the shared config:
export default {
extends: ['@gfmio/config-commitlint/commitlint.config.ts'],
rules: {
'scope-enum': [2, 'always', ['api', 'web', 'mobile', 'shared', 'docs']],
'subject-max-length': [2, 'always', 100],
'body-max-line-length': [2, 'always', 100]
}
};Configuration Highlights
This configuration enforces Conventional Commits with opinionated defaults designed to maintain high-quality commit history while remaining practical for day-to-day development.
Commit Message Format
<type>(<scope>): <subject>
<body>
<footer>Example:
feat(api): add user authentication endpoint
Implement JWT-based authentication with refresh tokens.
Includes middleware for protected routes.
Closes #123Type Enforcement
Allowed types (strictly enforced):
feat: New featuresfix: Bug fixesdocs: Documentation changesstyle: Code style changes (formatting, missing semicolons, etc.)refactor: Code refactoring without functional changesperf: Performance improvementstest: Adding or updating testsbuild: Build system or external dependency changesci: CI/CD configuration changeschore: Other changes that don't modify src or test filesrevert: Revert previous commits
Scope Guidelines
Recommended scopes (warning if missing):
config: Configuration file changesdeps: Dependency updatesci: CI/CD pipeline changesrelease: Release-related changes
Note: While these scopes are recommended in the base config, you should override scope-enum with project-specific scopes relevant to your codebase (e.g., package names in monorepos, feature areas, or module names).
Subject Line Rules
Strictly enforced:
- Must not start with uppercase (except proper nouns)
- Must not use PascalCase
- Should be concise and descriptive
Good examples:
feat(api): add rate limiting middleware
fix(auth): resolve token expiration edge case
docs(readme): update installation instructionsBad examples:
feat(api): Add rate limiting middleware ❌ (uppercase 'Add')
fix(auth): ResolveTokenIssue ❌ (PascalCase)
Feat(api): add feature ❌ (uppercase type)Workflow Integration
Husky + Git Hooks
Install husky to validate commits locally:
npm install --save-dev husky
npx husky initCreate .husky/commit-msg:
#!/usr/bin/env sh
npx --no -- commitlint --edit $1Make it executable:
chmod +x .husky/commit-msgNow every commit will be validated before it's created.
Package Scripts
Add these to your package.json:
{
"scripts": {
"commitlint": "commitlint --edit",
"commitlint:check": "commitlint --from HEAD~1 --to HEAD --verbose"
}
}Testing Commit Messages
Test a commit message manually:
echo "feat(api): add new endpoint" | npx commitlintCheck recent commits:
npx commitlint --from HEAD~3 --to HEAD --verboseCI/CD Integration
GitHub Actions
name: Lint Commits
on: [push, pull_request]
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@v2
- run: bun install
- name: Validate PR commits
if: github.event_name == 'pull_request'
run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose
- name: Validate push
if: github.event_name == 'push'
run: npx commitlint --from HEAD~1 --to HEAD --verboseValidating PR Titles
Many projects squash commits and use PR titles as commit messages. Add this to your workflow:
- name: Lint PR title
if: github.event_name == 'pull_request'
run: echo "$PR_TITLE" | npx commitlint --verbose
env:
PR_TITLE: ${{ github.event.pull_request.title }}Customization Examples
Monorepo with Package Scopes
export default {
extends: ['@gfmio/config-commitlint/commitlint.config.ts'],
rules: {
'scope-enum': [
2,
'always',
[
'api',
'web',
'mobile',
'shared',
'docs',
'config',
'deps',
'ci',
'release'
]
],
'scope-empty': [2, 'never'] // Require scope in monorepos
}
};Enforce Body and Footer
export default {
extends: ['@gfmio/config-commitlint/commitlint.config.ts'],
rules: {
'body-min-length': [2, 'always', 20],
'footer-max-line-length': [2, 'always', 100]
}
};Custom Types for Specific Workflows
export default {
extends: ['@gfmio/config-commitlint/commitlint.config.ts'],
rules: {
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'build',
'ci',
'chore',
'revert',
'security', // Add custom types
'i18n',
'a11y'
]
]
}
};Relaxed Configuration
export default {
extends: ['@gfmio/config-commitlint/commitlint.config.ts'],
rules: {
'scope-empty': [0], // Disable scope requirement
'scope-enum': [0], // Disable scope validation
'subject-case': [1, 'never', ['upper-case']] // Only warn on uppercase
}
};Philosophy
This configuration follows these principles:
- Enforce consistency: Strict type validation ensures uniform commit history
- Enable automation: Conventional Commits enable automated changelog generation and semantic versioning
- Improve readability: Clear structure makes commit history scannable and meaningful
- Support tooling: Compatible with release-please, semantic-release, and conventional-changelog
- Stay practical: Warnings for recommended practices, errors only for critical format violations
- Allow flexibility: Easy to extend and customize for project-specific needs
Why Conventional Commits?
Conventional Commits provide:
- Automated versioning: Tools can determine version bumps (major/minor/patch) from commit types
- Changelog generation: Automatic, accurate changelogs grouped by type
- Better navigation: Quickly find features, fixes, or breaking changes in history
- Clear communication: Team members understand changes at a glance
- Integration ready: Works seamlessly with CI/CD, release automation, and project management tools
Common Patterns
Breaking Changes
Indicate breaking changes with ! or BREAKING CHANGE: in footer:
feat(api)!: change authentication response format
BREAKING CHANGE: The auth endpoint now returns { token, user } instead of just the token string.Multiple Scopes
Choose the primary scope or use a general one:
refactor(api,web): standardize error handlingReferencing Issues
Use the footer to reference issues:
fix(auth): resolve session timeout bug
The session was expiring too early due to incorrect timestamp comparison.
Fixes #123
Relates to #456Work in Progress
For WIP commits during feature development:
feat(api): add user endpoint (WIP)
chore: temporary debug loggingClean these up before merging or squash them into meaningful commits.
Editor Integration
VS Code
Install Conventional Commits extension:
code --install-extension vivaxy.vscode-conventional-commitsThis provides a GUI for creating properly formatted commit messages.
JetBrains IDEs
Use the Conventional Commit plugin for WebStorm, IntelliJ IDEA, etc.
Command Line Helper
Install commitizen for interactive commit message creation:
npm install --save-dev commitizen cz-conventional-changelogAdd to package.json:
{
"scripts": {
"commit": "cz"
},
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
}Then use npm run commit instead of git commit.
Troubleshooting
Commits Failing Validation
Run commitlint with verbose output to see which rule failed:
npx commitlint --from HEAD~1 --to HEAD --verboseTesting Configuration
Verify your config loads correctly:
npx commitlint --print-configCommon Errors
Error: "subject may not be empty"
- Ensure your commit message has a subject after the type and scope
Error: "type must be one of [feat, fix, ...]"
- Use only allowed types or extend
type-enumrule
Error: "scope must be one of [...]"
- Either add a valid scope or override
scope-enumin your config
Migration from Other Conventions
From No Convention
- Install this config and husky
- Start using conventional commits for new work
- Optionally use
git rebase -ito clean up feature branch history before merging
From Angular Commit Guidelines
This config extends @commitlint/config-conventional, which is based on Angular's convention. You may only need to adjust scope enums.
From Custom Convention
Review your current types and map them to conventional types, or extend type-enum to include your custom types.
Requirements
- Node.js 18+ or Bun
- commitlint
^20.0.0or later - Git
License
Author
Frédérique Mittelstaedt
- GitHub: @gfmio
Contributing
Issues and pull requests are welcome! This is a personal configuration, but suggestions for improvements are appreciated.
