Getting started
relizy commitlint ships with Relizy: install Relizy and you are ready.
pnpm add -D relizynpm install -D relizyyarn add -D relizybun add -D relizyNo config is required: the linter reads your relizy.config.ts. See Configuration to tune it.
Lint the commit being created
The commit-msg hook lints every commit before it is created.
With the install command
npx relizy commitlint --installIt writes the commit-msg hook:
- in
.husky/when husky is set up; - otherwise in the hooks directory of git (
core.hooksPathor.git/hooks).
An existing commit-msg hook is never replaced silently: add the command to it, or run relizy commitlint --install --force.
By hand
# .husky/commit-msg
npx --no -- relizy commitlint --edit "$1"{
"simple-git-hooks": {
"commit-msg": "npx --no -- relizy commitlint --edit \"$1\""
}
}# lefthook.yml
commit-msg:
commands:
relizy-commitlint:
run: npx --no -- relizy commitlint --edit {1}--edit reads the message file given by git (.git/COMMIT_EDITMSG by default) and ignores the comment lines git adds in the editor. The staged files are used for the scope rules.
Read the output
A valid commit prints one line, with its effect on the next release:
✔ feat(nuxt) → minor bump, 🚀 EnhancementsAn invalid commit prints each problem with how to fix it, a corrected header when the mistakes can be fixed safely (case, spacing, typos in the type or the scope, final period), the documentation of the failing rules, and how to commit again. The hook stops the commit:
✖ fix(nuxtt): Typo.
✖ scope-enum The scope "nuxtt" is not allowed
→ did you mean "nuxt"? use a workspace package or one of: nuxt,
@maz-ui/nuxt, core, @maz-ui/core
✖ subject-case The subject starts with an uppercase letter
→ start it lowercase, relizy capitalizes it in the changelog
✖ subject-full-stop The subject ends with a period
→ remove the final period
✖ subject-meaningful The subject "Typo." does not describe the change
→ describe what changed, in at least 2 words or 15 characters
Suggested header: fix(nuxt): typo
still to fix: subject-meaningful
────────────────────────────────────────────────────────────────────────
✖ The commit message is invalid: 4 errors, 0 warnings
Rules: scope-enum https://relizy.dev/commitlint/rules#scope-enum
subject-case https://relizy.dev/commitlint/rules#subject-case
subject-full-stop https://relizy.dev/commitlint/rules#subject-full-stop
subject-meaningful https://relizy.dev/commitlint/rules#subject-meaningful
Fix: edit the message and commit again, it is kept in .git/COMMIT_EDITMSG:
$ git commit --edit --file .git/COMMIT_EDITMSGWarnings are printed but never stop the commit. Add --preview to also print the changelog entry of the commit.
The output is colored in a terminal and in GitHub Actions or GitLab CI, and plain text otherwise, e.g. when an AI agent runs the command. Set NO_COLOR=1 or FORCE_COLOR=1 to choose. For programs and AI agents, --format json prints the same report as JSON (see CLI).
Lint the commits of a pull request
A commit can skip the hook: --no-verify, a commit made in the web interface of GitHub or GitLab, a squash merge... Lint the commits of your pull requests in CI as well:
npx relizy commitlintWithout --from, Relizy lints:
- in a GitHub Actions pull request, the commits after the merge-base with the target branch;
- in a GitLab CI merge request, the commits after the base of the merge request;
- otherwise, the commits after the last tag.
If your pull or merge requests are squash merged, lint their title too: it becomes the message of the commit that lands on the target branch, the one Relizy reads for the bump and the changelog. Enable it with commitlint.title or --title. The draft markers of GitLab (Draft:, [Draft]) are removed.
import { defineConfig } from 'relizy'
export default defineConfig({
commitlint: {
title: true,
},
})Merge commits, fixup!, squash! and amend! commits and the release commits of Relizy are ignored. See CLI for every option.
When a commit is invalid, the summary ends with how to fix it:
────────────────────────────────────────────────────────────────────────
✖ 1 of 3 commits and the merge request title are invalid: 2 errors, 0 warnings
Rules: subject-case https://relizy.dev/commitlint/rules#subject-case
header-format https://relizy.dev/commitlint/rules#header-format
Fix: reword 1a2b3c4: mark it as "reword" in the rebase, then force-push:
$ git rebase -i 9f8e7d6
$ git push --force-with-lease
edit the merge request title, then run a new pipeline (a retry keeps the old title)Add --quiet to only print the commits with problems on large pull requests. In GitHub Actions, each problem is also reported as an annotation, visible in the summary of the job and on the pull request.
Full history
The CI must fetch the history of the base branch, otherwise the start of the range cannot be found: fetch-depth: 0 on actions/checkout, GIT_DEPTH: 0 on GitLab CI. Relizy tells you so when it runs in a shallow clone.
# .github/workflows/commitlint.yml
name: Commit messages
on:
pull_request:
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # The history of the base branch is needed for the merge-base
- uses: actions/setup-node@v6
with:
node-version: 22
- run: npm ci
- run: npx relizy commitlint# .gitlab-ci.yml
commitlint:
image: node:22
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
variables:
GIT_DEPTH: 0
script:
- npm ci
- npx relizy commitlintNext steps
- Rules: what is checked and how to tune it.
- Custom Rules: write your own rules as functions.
- Migrating from commitlint: replace your commitlint config.