Toolbox
Shelf

Pages

  • Home
  • Shelf
  • Toolbox

Extras

  • Resume

Crafted with and few cups of coffee.

Designed in Figma • Built with Next.js & Tailwind • Hosted on Vercel

© 2025 Gentle Joseph | All rights reserved.

December 9th, 2024•7 min read

Commitizen: Writing Better Git Commits with Conventional Commits

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.

What is Commitizen?

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.

Why Use Conventional Commits?

Conventional Commits provide a standardized format for commit messages that:

  • Improves readability - Clear structure makes commits easier to scan
  • Enables automation - Tools can automatically generate changelogs and determine semantic versioning
  • Better collaboration - Team members understand changes at a glance
  • Easier debugging - Find specific types of changes quickly

The format looks like this:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Installing Commitizen

Global Installation

# Install globally with npm
npm install -g commitizen

# Install globally with yarn
yarn global add commitizen

# Install globally with pnpm
pnpm add -g commitizen

Project Installation

# Install as dev dependency
npm install --save-dev commitizen

# Add to package.json scripts
npm set-script commit "cz"

Installing the Conventional Changelog Adapter

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"
    }
  }
}

Using Commitizen

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

Commit Types Explained

Here are the standard commit types and when to use them:

feat - New Features

feat: add user authentication system
feat(auth): implement OAuth2 login
feat(api): add user profile endpoints

fix - Bug Fixes

fix: resolve login redirect issue
fix(auth): handle expired token correctly
fix(ui): correct button alignment on mobile

docs - Documentation

docs: update README installation steps
docs(api): add endpoint documentation
docs: fix typos in contributing guide

style - Code Style

style: fix eslint warnings
style: format code with prettier
style: remove trailing whitespace

refactor - Code Refactoring

refactor: simplify user validation logic
refactor(auth): extract token helper functions
refactor: migrate to TypeScript

perf - Performance Improvements

perf: optimise database queries
perf(images): implement lazy loading
perf: reduce bundle size by 20%

test - Tests

test: add unit tests for auth service
test(e2e): add login flow tests
test: improve test coverage to 90%

chore - Maintenance

chore: update dependencies
chore(deps): bump lodash to 4.17.21
chore: configure CI/CD pipeline

ci - Continuous Integration

ci: add GitHub Actions workflow
ci: fix Docker build process
ci: update deployment script

build - Build System

build: update webpack configuration
build: add production optimisation
build(deps): upgrade to Node 18

Advanced Features

Scopes

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

Breaking Changes

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.

Multiple Line Commits

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

Setting Up Git Aliases

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'

Team Configuration

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"
    }
  }
}

Custom Adapters

You can create custom adapters for specific project needs. Popular alternatives include:

cz-emoji

Adds emoji to commit messages:

npm install --save-dev cz-emoji

Example output: ✨ feat: add new feature

cz-customizable

Highly customizable adapter:

npm install --save-dev cz-customizable

Create a .cz-config.js file to define custom prompts and types.

Integration with Tools

Husky + Commitlint

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',
      ],
    ],
  },
};

Semantic Release

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"
    ]
  }
}

Best Practices

  1. Be specific - Use clear, descriptive commit messages
  2. Use present tense - "add feature" not "added feature"
  3. Limit subject line - Keep it under 50 characters
  4. Use body for context - Explain why, not what
  5. Reference issues - Include ticket numbers when applicable
  6. Review before committing - Double-check your message

Common Patterns

Feature Development

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

Bug Fixes

fix(auth): resolve token expiration issue
test(auth): add test for token refresh
docs(auth): update authentication guide

Refactoring

refactor(api): extract validation middleware
refactor(api): simplify error handling
test(api): update tests for refactored code

Troubleshooting

Commitizen not working

# Check if commitizen is installed
npx cz --version

# Verify adapter configuration
cat package.json | grep -A 5 commitizen

Custom adapter not loading

# Check adapter installation
npm list cz-conventional-changelog

# Verify path in package.json

Prompts not showing

# Try running with explicit adapter
npx cz --adapter=cz-conventional-changelog

Migration Strategy

For Existing Projects

  1. Start gradually - Begin using commitizen for new commits
  2. Train the team - Share this guide and best practices
  3. Set up automation - Add linting and release automation
  4. Review and iterate - Adjust rules based on team feedback

Example Migration Script

#!/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"

Conclusion

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:

  1. Install Commitizen in your current project
  2. Try it for a few commits to get comfortable
  3. Set up team guidelines and automation
  4. Explore semantic release for automated versioning

Happy committing! 🚀

Back to Shelf