Lint your commit messages
commitlint is a Git commit message linter that enforces conventional commit formats across your codebase. With over 559,000 weekly downloads, it validates commit messages against predefined rules before they enter your repository history. The package checks that commits follow patterns like type(scope): subject, rejecting malformed messages at commit-time rather than during code review.
The tool exists to solve a persistent problem in software teams: inconsistent commit history. Without enforcement, developers write commits ranging from "fix bug" to "WIP" to "updated stuff", making it impossible to generate changelogs automatically, understand project history, or implement semantic versioning. commitlint transforms commits into structured data that tools can parse, enabling automation around releases, changelogs, and project analytics.
Typically deployed as a Git hook via Husky, commitlint runs in milliseconds during the commit process. It's commonly paired with @commitlint/config-conventional for out-of-the-box conventional commit rules, though teams can customize every validation rule. Major open-source projects and enterprises use it to maintain clean Git history across distributed teams, where manual enforcement is impractical.
The package integrates into existing workflows without runtime overhead—it's a devDependency that only runs locally and in CI. Developers can use it alongside Commitizen for guided commit authoring or standard-version for automated releases, creating a complete conventional commit toolchain.
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']
],
'scope-enum': [
2,
'always',
['api', 'ui', 'auth', 'db', 'config']
],
'subject-case': [2, 'never', ['start-case', 'pascal-case', 'upper-case']],
'subject-max-length': [2, 'always', 72],
'body-max-line-length': [2, 'always', 100]
}
};
// package.json scripts
{
"scripts": {
"prepare": "husky install",
"commitlint": "commitlint --edit"
},
"devDependencies": {
"@commitlint/cli": "^20.4.2",
"@commitlint/config-conventional": "^20.4.2",
"husky": "^9.0.0"
}
}
// .husky/commit-msg (created by: npx husky add .husky/commit-msg 'npx commitlint --edit $1')
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx commitlint --edit $1
// Example valid commits:
// git commit -m "feat(api): add user authentication endpoint"
// git commit -m "fix(ui): resolve button alignment on mobile"
// git commit -m "docs: update API documentation for v2"
// Example rejected commits:
// git commit -m "fixed stuff" // Missing type format
// git commit -m "feat(invalid): add feature" // Scope not in enum
// git commit -m "FEAT: Add Feature" // Subject wrong caseEnforcing team commit standards: Large teams use commitlint in Husky's commit-msg hook to block non-compliant commits before they reach the remote repository. This prevents the "fix typo" and "asdf" commits that plague review history, ensuring every commit describes its purpose using conventional types like feat, fix, or chore.
Automated changelog generation: Projects using standard-version or semantic-release depend on commitlint to guarantee commit messages follow parseable formats. When every commit has a structured type and scope, tools can automatically generate changelogs grouped by feature additions, bug fixes, and breaking changes without manual curation.
CI/CD validation for pull requests: CI pipelines integrate commitlint to validate all commits in a PR against team standards before merge. The @commitlint/travis-cli package or custom CI scripts run commitlint on commit ranges, catching violations that bypassed local hooks and maintaining history quality in the main branch.
Monorepo scope enforcement: Teams with monorepos configure commitlint rules to require scopes matching package names (e.g., feat(api): add endpoint or fix(ui): resolve button state). This makes it trivial to filter commits by package when reviewing changes or generating per-package release notes.
Semantic versioning automation: Projects using semantic-release rely on commitlint to ensure commit types correctly signal version bumps—feat: triggers minor releases, fix: triggers patches, and BREAKING CHANGE: triggers majors. Without validation, incorrect commit types cause wrong version numbers in automated releases.
npm install commitlintpnpm add commitlintbun add commitlint