Good commit messages are the foundation of maintainable codebases. They help you understand what changed, why it changed, and how it impacts your project. But writing consistent, meaningful commit messages can be challenging. That's where Commitizen comes in.
Commitizen is a command-line tool that helps you write standardized commit messages following the Conventional Commits specification. Instead of struggling to remember commit message formats, Commitizen guides you through an interactive prompt to create well-structured commits.
Conventional Commits provide a standardized format for commit messages that:
The format looks like this:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
# Install globally with npm
npm install -g commitizen
# Install globally with yarn
yarn global add commitizen
# Install globally with pnpm
pnpm add -g commitizen
# Install as dev dependency
npm install --save-dev commitizen
# Add to package.json scripts
npm set-script commit "cz"
Commitizen needs an adapter to define the commit format. The most popular is
cz-conventional-changelog
:
# Install the adapter
npm install --save-dev cz-conventional-changelog
# Configure it in package.json
npx commitizen init cz-conventional-changelog --save-dev --save-exact
Or add this configuration manually to your package.json
:
{
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
Once installed, replace git commit
with git cz
or npm run commit
:
# Instead of this
git add .
git commit -m "fix something"
# Do this
git add .
git cz
Commitizen will then prompt you through an interactive questionnaire:
? Select the type of change that you're committing: (Use arrow keys)
❯ feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests or correcting existing tests
Here are the standard commit types and when to use them:
feat: add user authentication system
feat(auth): implement OAuth2 login
feat(api): add user profile endpoints
fix: resolve login redirect issue
fix(auth): handle expired token correctly
fix(ui): correct button alignment on mobile
docs: update README installation steps
docs(api): add endpoint documentation
docs: fix typos in contributing guide
style: fix eslint warnings
style: format code with prettier
style: remove trailing whitespace
refactor: simplify user validation logic
refactor(auth): extract token helper functions
refactor: migrate to TypeScript
perf: optimise database queries
perf(images): implement lazy loading
perf: reduce bundle size by 20%
test: add unit tests for auth service
test(e2e): add login flow tests
test: improve test coverage to 90%
chore: update dependencies
chore(deps): bump lodash to 4.17.21
chore: configure CI/CD pipeline
ci: add GitHub Actions workflow
ci: fix Docker build process
ci: update deployment script
build: update webpack configuration
build: add production optimisation
build(deps): upgrade to Node 18
Scopes provide additional context about what part of the codebase was affected:
feat(auth): add login functionality
fix(ui): resolve mobile navigation bug
docs(api): update endpoint documentation
For changes that break backward compatibility, add !
after the type/scope or
include BREAKING CHANGE:
in the footer:
feat!: remove deprecated API endpoints
BREAKING CHANGE: The /v1/users endpoint has been removed. Use /v2/users instead.
For complex changes, provide a detailed body and footer:
feat(auth): implement OAuth2 authentication
Add support for Google and GitHub OAuth2 providers.
Users can now sign in using their existing accounts
from these platforms.
Closes #123
Reviewed-by: @teammate
Make it even easier by setting up Git aliases:
# Add to your .gitconfig
git config --global alias.cz '!npx cz'
# Or add this alias to your shell
alias gcz='git cz'
For consistent team usage, add these scripts to your package.json
:
{
"scripts": {
"commit": "cz",
"commit:signed": "cz --signoff"
},
"husky": {
"hooks": {
"prepare-commit-msg": "exec < /dev/tty && npx cz --hook || true"
}
}
}
You can create custom adapters for specific project needs. Popular alternatives include:
Adds emoji to commit messages:
npm install --save-dev cz-emoji
Example output: ✨ feat: add new feature
Highly customizable adapter:
npm install --save-dev cz-customizable
Create a .cz-config.js
file to define custom prompts and types.
Enforce conventional commits with validation:
# Install commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Install husky
npm install --save-dev husky
# Setup husky
npx husky install
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
Create commitlint.config.js
:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'chore',
'ci',
'build',
],
],
},
};
Automatically generate releases and changelogs:
npm install --save-dev semantic-release
Add to package.json
:
{
"release": {
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github"
]
}
}
feat(user): add user profile page
feat(user): implement profile editing
feat(user): add profile picture upload
test(user): add profile component tests
docs(user): document profile API endpoints
fix(auth): resolve token expiration issue
test(auth): add test for token refresh
docs(auth): update authentication guide
refactor(api): extract validation middleware
refactor(api): simplify error handling
test(api): update tests for refactored code
# Check if commitizen is installed
npx cz --version
# Verify adapter configuration
cat package.json | grep -A 5 commitizen
# Check adapter installation
npm list cz-conventional-changelog
# Verify path in package.json
# Try running with explicit adapter
npx cz --adapter=cz-conventional-changelog
#!/bin/bash
# setup-commitizen.sh
echo "Setting up Commitizen..."
# Install dependencies
npm install --save-dev commitizen cz-conventional-changelog
# Configure commitizen
npx commitizen init cz-conventional-changelog --save-dev --save-exact
# Add npm script
npm set-script commit "cz"
# Setup git alias
git config alias.cz '!npx cz'
echo "✅ Commitizen setup complete!"
echo "Use 'npm run commit' or 'git cz' for your next commit"
Commitizen transforms the way you write commit messages by providing structure, consistency, and automation capabilities. While it might feel like extra overhead initially, the long-term benefits of readable history, automated releases, and better collaboration make it invaluable for any serious development project.
Start small, be consistent, and watch your Git history become a valuable documentation resource for your project's evolution.
Next steps:
Happy committing! 🚀