Skip to main content

Commitlint: Conventional Commits Setup & Team Enforcement Guide

Commitlint validates that your commit messages follow a consistent format. Combined with the Conventional Commits specification and Husky, it ensures every commit in your repo is machine-readable — enabling automated CHANGELOGs, semantic version bumps, and clean release notes without manual work.

✓ Blocks malformed commits at the hook level ✓ Automated CHANGELOG generation ✓ Semantic versioning from commit types ✓ CI enforcement via GitHub Actions

The Conventional Commits Format

Every commit message follows this structure:

type(scope): short description

[optional body]

[optional footer: BREAKING CHANGE: description]
Type Meaning Version Bump
feat New feature MINOR (1.x.0)
fix Bug fix PATCH (1.0.x)
feat! / fix! Breaking change MAJOR (x.0.0)
chore / docs / refactor No user-facing change No bump

Commitlint Installation and Config

npm install --save-dev @commitlint/cli @commitlint/config-conventional
// commitlint.config.js
export default {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'perf', 'ci', 'revert']],
    'subject-case': [2, 'never', ['upper-case', 'pascal-case', 'start-case']],
    'header-max-length': [2, 'always', 100],
  }
};

Integrating with Husky commit-msg Hook

# After npx husky init:
# .husky/commit-msg
npx --no -- commitlint --edit $1

# Test it manually:
echo "bad commit message" | npx commitlint
# ✖ type may not be empty [type-empty]
echo "feat: add dark mode toggle" | npx commitlint
# ✔ all rules pass

Generating CHANGELOGs with standard-version

npm install --save-dev standard-version

# Preview what would be released:
npx standard-version --dry-run

# Cut a release (bumps version, updates CHANGELOG.md, commits, tags):
npx standard-version

# Force a specific bump:
npx standard-version --release-as minor

standard-version reads commits since the last git tag and groups them by type in CHANGELOG.md. feat commits go under Features, fix under Bug Fixes. BREAKING CHANGE footer entries get their own section.

CI Enforcement via GitHub Actions

# .github/workflows/commitlint.yml
name: Commitlint
on: [pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: wagoid/commitlint-github-action@v6

standard-version vs release-please

Feature standard-version release-please
Trigger Manual CLI Automatic GitHub Action
Release PR No Yes (reviewable before merge)
Maintenance Deprecated (use standard-version v5) Actively maintained by Google
Best for Simple projects, local control Teams, fully automated pipelines
Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →

Frequently Asked Questions

What is the Conventional Commits specification?▼

Conventional Commits is a lightweight convention on top of commit messages. The format is: type(scope): description. Common types are feat (new feature), fix (bug fix), docs, style, refactor, test, and chore. An optional ! after the type marks breaking changes, which map to a MAJOR version bump in semantic versioning. The spec is designed so tooling can parse commit history to generate changelogs and determine version bumps automatically.

How do I configure custom types in Commitlint?▼

In commitlint.config.js, extend the base config and override the type-enum rule: export default { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'chore', 'perf', 'ci', 'revert', 'build', 'wip']] } }. The first element is severity (2 = error), the second is 'always' or 'never', and the third is the list of allowed values. You can also add scope-enum and footer-max-line-length rules.

How do I generate a CHANGELOG from Conventional Commits?▼

Run npx standard-version or npx release-please. standard-version reads git log since the last tag, groups commits by type, and writes a CHANGELOG.md section with links to each commit. It also bumps package.json version based on commit types (feat → minor, fix → patch, breaking → major) and creates a version tag. Run it locally with: npx standard-version --dry-run to preview changes before committing.

What is the difference between standard-version and release-please?▼

standard-version is a local CLI tool: you run it manually (or in CI), it bumps the version, updates CHANGELOG.md, commits, and tags. It is simple but requires manual triggering. release-please is a GitHub Action maintained by Google that automates the full release cycle: it opens a 'Release PR' that updates CHANGELOG and version, and merges it when you are ready. release-please is better for teams that want a fully automated, PR-based release workflow.

How do I enforce Commitlint in GitHub Actions?▼

Add a workflow that checks out with full depth (fetch-depth: 0) and runs commitlint on the range of commits in the PR. Use the action: uses: wagoid/commitlint-github-action@v6. This action reads your commitlint.config.js and validates every commit in the pull request. If any commit fails the rules, the check fails and the PR cannot be merged.

How do I add Commitlint to an existing project?▼

Install: npm install --save-dev @commitlint/cli @commitlint/config-conventional. Create commitlint.config.js with: export default { extends: ['@commitlint/config-conventional'] }. Add the commit-msg hook via Husky: echo 'npx --no -- commitlint --edit $1' > .husky/commit-msg. Your existing commit history is not affected — Commitlint only validates new commits from this point forward.