Make everyone in your project write beautiful commit messages using commitlint and commitizen ๐Ÿš€

Make everyone in your project write beautiful commit messages using commitlint and commitizen ๐Ÿš€

Compose and enforce meaningful commit messages for your projects using commitlint and commitizen with emojis โœจ ๐Ÿš€ ๐Ÿ›

ยท

5 min read

When working on a project many people don't have the time to write meaningful commit messages. For me, I have to work with many other developers which involve reviewing their commits, reviewing merge requests, creating and fixing stuff, etc. And all that simultaneously for multiple projects. Often their commit message does not describe what changes did they did in that current commit, and I have to dig through their code to understand that, and it can be a nightmare sometimes.

Even if they write a good message, many people have their own style or convention of writing their commit messages. To solve this particular problem I started using commitlint along with commitizen so that my team adheres to a commit convention.

Sneak peek to the end result ๐Ÿ‘‡ commitizen.gif

Step 1: Setup husky and commitlint

Firstly, you will need husky, which is used for writing git hooks. See More

Install husky to your project.

npx husky-init && npm install

or, if you prefer yarn like me

npx husky-init && yarn

Next, we are going to install commitlint and commitlint-config-gitmoji

yarn add -D @commitlint/cli commitlint-config-gitmoji

or,

npm install --save-dev @commitlint/cli commitlint-config-gitmoji

The @commitlint/cli will be used to check if our commit message follows the convention we configured for the project and the commitlint-config-gitmoji is the commit convention preset we will be using. There are other conventions as well which you can use.

The commitlint-config-gitmoji follows the below convention.

You need to provide a emoji (or gitmoji) then a type, following a scope (not mandatory), and then the subject, which is your actual commit message. You can add a body and footer too if you like.

:gitmoji: type(scope?): subject
body?
footer?

Example,

โœจ feat(api): add middleware for user authentication

Now, we need to define the commitlint config for our project. Create a file named commitlint.config.js and define your config given below.

module.exports = {
  extends: ['gitmoji'],
  rules: {
    'header-max-length': [0, 'always', 100],
  },
};

You can customize the rules of your commit message per you like similarly to eslint. See here

Step 2: Add commitlint checking as a git hook

Next, we need to add commitlint as a git hook using husky to check our commit message before every commit. To do this run the below command.

yarn husky add .husky/commit-msg 'yarn commitlint --edit "$1"'

OR

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

This will create a file named commit-msg inside your project inside .husky folder.

Note: husky by default creates a pre-commit file, which runs npm test. If you don't have a test script defined in your package.json it will throw an error. You can remove the npm test line from the pre-commit file or add a valid test script.

Now try to do a commit ๐Ÿ˜

image.png

Well now my fellow teammates cannot commit unless they write a proper commit message ๐Ÿ˜ˆ.

commitlint prevents us from doing a commit if the commit message does not adhere to the structure provided by commitlint-config-gitmoji.

Step 3: Adding commitizen cli for composing commit messages

Coming to the last part, now we will create a CLI helper to generate the commit message using commitizen. Also we are using cz-customizable to customize the CLI helper.

yarn add -D commitizen cz-customizable

OR

npm install --save-dev commitizen cz-customizable

Next, add a commitizen config in your package.json like below

{
  ....
  "devDependencies": {
    ...,
  },
  "config": {
    "commitizen": {
      "path": "cz-customizable"
    }
  }
}

Now create a file in your root folder named .cz-config.js to customize the options of the CLI helper, and paste the below config.

module.exports = {
  types: [
    { value: ':sparkles: feat', name: 'โœจ feat:\tAdding a new feature' },
    { value: ':bug: fix', name: '๐Ÿ› fix:\tFixing a bug' },
    { value: ':memo: docs', name: '๐Ÿ“ docs:\tAdd or update documentation' },
    {
      value: ':lipstick: style',
      name: '๐Ÿ’„ style:\tAdd or update styles, ui or ux',
    },
    {
      value: ':recycle: refactor',
      name: 'โ™ป๏ธ  refactor:\tCode change that neither fixes a bug nor adds a feature',
    },
    {
      value: ':zap: perf',
      name: 'โšก๏ธ perf:\tCode change that improves performance',
    },
    {
      value: ':white_check_mark: test',
      name: 'โœ… test:\tAdding tests cases',
    },
    {
      value: ':truck: chore',
      name: '๐Ÿšš chore:\tChanges to the build process or auxiliary tools\n\t\tand libraries such as documentation generation',
    },
    { value: ':rewind: revert', name: 'โช๏ธ revert:\tRevert to a commit' },
    { value: ':construction: wip', name: '๐Ÿšง wip:\tWork in progress' },
    {
      value: ':construction_worker: build',
      name: '๐Ÿ‘ท build:\tAdd or update regards to build process',
    },
    {
      value: ':green_heart: ci',
      name: '๐Ÿ’š ci:\tAdd or update regards to build process',
    },
  ],

  scopes: [
    { name: 'ui' },
    { name: 'android' },
    { name: 'ios' },
    { name: 'home' },
    { name: 'planner' },
    { name: 'settings' },
  ],

  scopeOverrides: {
    fix: [{ name: 'merge' }, { name: 'style' }, { name: 'test' }, { name: 'hotfix' }],
  },

  allowCustomScopes: true,
  allowBreakingChanges: ['feat', 'fix'],
  // skip any questions you want
  skipQuestions: ['body'],
  subjectLimit: 100,
};

Also, add a npm script to run the commitizen cli.

{
  "scripts": {
    ...,
    "cm": "cz"
  },
  "dependencies": {
    ...
  }
}

You can modify the config as per your choice. See here

Now run the script to see commitizen in action.

yarn cm

OR

npm run cm

Ta-da, now you and everyone in your team can easily write beautiful conventional commit messages.

image.png

ย