We use cookies to understand how the site is used and to display ads. Analytics and advertising only run after you accept. You can change your choice anytime. Privacy policy

Skip to content
devvkit
$devvkit learn --librarie commitlint:-commit-message-linter-guide

commitlint: Commit Message Linter Guide

[oss-stack][commits][conventional-commits][ci]
Open Source
Install
npm install --save-dev @commitlint/cli @commitlint/config-conventional
npx commitlint --from HEAD~1 --to HEAD

commitlint validates commit messages against a rule set. Paired with @commitlint/config-conventional it enforces the Conventional Commits spec: valid type, optional scope format, no trailing period, correct breaking-change syntax. Anything invalid blocks the commit: in a pre-commit hook locally, or in CI for anything that slips through.

The real value is upstream automation: a history that always passes commitlint guarantees semantic-release and changelog generators work, because their inputs are structurally predictable. It is the cheapest CI step you can add to an open source project.

Setup

Install config· Standard conventional config out of the box.
npm install --save-dev @commitlint/cli @commitlint/config-conventional

# commitlint.config.js:
module.exports = { extends: ["@commitlint/config-conventional"] }

Rules

Lint the last commits· Verify history or a specific range.
# Most recent commit:
npx commitlint --from HEAD~1 --to HEAD

# Last 5 commits:
npx commitlint --from HEAD~5

# A single message (also how CI bots validate):
echo "feat: add search" | npx commitlint
Custom rules· Allow project-specific types and scopes.
module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    "type-enum": [2, "always", ["feat", "fix", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert", "release"]],
    "scope-enum": [2, "always", ["api", "cli", "web", "deps"]],
    "header-max-length": [2, "always", 72]
  }
}

Git Hooks

Pre-commit hook with husky· Catch bad messages locally.
npx husky init
# .husky/prepare-commit-msg:
npx --no -- commitlint --edit "$1"

# Optional: also lint the message before it is finalized
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"

CI Integration

CI check· Guard the default branch against hand-typed history.
# GitHub Actions step:
match: \"--from:${{ github.event.pull_request.base.sha }}--"
steps:
  - uses: actions/checkout@v4
    with:
      fetch-depth: 0
  - run: npm ci
  - run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }}