Conventional Commits 1.0.0 (conventionalcommits.org (https://www.conventionalcommits.org/en/v1.0.0/ 96,043 )) gives the subject line a structure a program can parse: <type>[(scope)][!]: <description>, then an optional body and footers. The specification defines only two types, and ties them to Semantic Versioning (Semantic Version Tags): fix means a patch release and feat a minor release, while a ! before the colon or a BREAKING CHANGE: footer means a major release whatever the type. The widely used Angular 42,088 convention adds docs, test, refactor, perf, build, ci, chore and style, which trigger no release.
commitlint 18,754 (github.com/conventional-changelog/commitlint (https://github.com/conventional-changelog/commitlint 18,754 ), MIT, version 21.2.3) checks a message against such rules. Sam replaces BookNest's hand-written commit-msg hook of commit-msg Hook with it:
git switch -q main
npm install --save-dev --silent @commitlint/cli @commitlint/config-conventional
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.mjs
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg
echo "Add ?minRating= to /api/books" | npx commitlint
echo "feat(api): Add ?minRating= to /api/books" | npx commitlint
git add -A && git commit -qm "build: check commit messages with commitlint"
git push -q && git log --oneline -1⧗ --- input --- Add ?minRating= to /api/books ✖ subject may not be empty [subject-empty] ✖ type may not be empty [type-empty] ... ⧗ --- input --- feat(api): Add ?minRating= to /api/books ✖ subject must not be sentence-case [subject-case] ... d396523 build: check commit messages with commitlint
The .mjs extension allows export in a commonjs package, and npx --no never downloads a missing commitlint. The second rejection surprises most people: the conventional rules want a lowercase description, the opposite of BookNest's old rule. Old commits stay as they are, and release tools skip what they cannot parse.
Semantic release is the payoff: a tool reads the messages since the last tag, computes the next version, writes the changelog and tags the release.
| Tool | Runs | What it does | License |
|---|---|---|---|
| semantic-release 25.0.9 24,069 | In CI on every push | Versions, tags, publishes, writes release notes | MIT |
| release-please 17.11.2 7,559 | In CI (GitHub 29 ) | Keeps a release pull request up to date | Apache-2.0 |
| commit-and-tag-version 13.2.1 655 | Locally | Bumps, writes CHANGELOG.md, commits and tags | ISC |
| git-cliff 2.14.2 12,272 | Anywhere | Changelog from templates; Rust binary | MIT or Apache-2.0 |
semantic-release needs CI and push rights, so it belongs to GitHub. Here BookNest uses commit-and-tag-version, the maintained fork of the deprecated standard-version 7,984 , which touches only the local repository (Release and Hotfix Branches).