Make everyone in your project write beautiful commit messages using commitlint and commitizen 🚀
Tags: github, node, commit
Published: 2021-09-02 17:21:04

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eh8aasjdgi0427oxmkx5.gif)

## Step 1: Setup `husky` and `commitlint`

Firstly, you will need `husky`, which is used for writing git hooks. [See More](https://typicode.github.io/husky/#/)

Install `husky` to your project.

```sh
npx husky-init && npm install
```
or, if you prefer yarn like me
```
npx husky-init && yarn
```

Next, we are going to install [commitlint](https://commitlint.js.org/) and [commitlint-config-gitmoji](https://github.com/arvinxx/gitmoji-commit-workflow)

```sh
yarn add -D @commitlint/cli commitlint-config-gitmoji
```
or,
```sh
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](https://gitmoji.dev/)) 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.

```js
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](https://commitlint.js.org/#/reference-rules)

## 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.

```sh
yarn husky add .husky/commit-msg 'yarn commitlint --edit "$1"'
```
OR
```sh
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](https://cdn.hashnode.com/res/hashnode/image/upload/v1630248528640/xDEjJPoPP.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`](https://github.com/leoforfree/cz-customizable) to customize the CLI helper.

```sh
yarn add -D commitizen cz-customizable
```
OR
```sh
npm install --save-dev commitizen cz-customizable
``` 

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

```json
{
  ....
  "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.

```js
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.

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

You can modify the config as per your choice. [See here](https://github.com/leoforfree/cz-customizable)

Now run the script to see `commitizen` in action.

```sh
yarn cm
```
OR 
```sh
npm run cm
```

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


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630253335632/w-j33BgXR.png)