Como padronizar mensagens nos commits de sua equipe utilizando husky e commitlint
Tags: webdev, husky, programming, git
Published: 2023-12-20 10:57:14

## Glossário

* [Introdução](#chapter-1)
* [O que é commitlint](#chapter-2)
* [Implementando commitlint no nosso projeto](#chapter-3)

### Introdução <a name="chapter-1"></a>

Este tutorial é a segunda parte de uma série de tutoriais utilizando a ferramenta [husky](https://typicode.github.io/husky/). Caso queira ver a primeira parte, onde ensino a fazer o setup do projeto detalhadamente, o link se encontra [aqui](https://dev.to/marcusicaro/como-adicionar-hooks-aos-commits-de-seu-projeto-utilizando-husky-32nh).

Veremos aqui uma maneira rápida e prática de padronizar suas mensagens de commit utilizando husky e [commitlint](https://commitlint.js.org/#/), para que você e sua equipe possam facilmente navegar pelo histórico de seus projetos.

### O que é commitlint <a name="chapter-2"></a>

Para fazer validações nas mensagens de commit antes do upload, utilizaremos novamente git hooks. Para uma explicação mais detalhada sobre o que são git hooks, leia a primeira parte desse tutorial [aqui](https://dev.to/marcusicaro/como-adicionar-hooks-aos-commits-de-seu-projeto-utilizando-husky-32nh). Adicionaremos um novo hook em nosso projeto, para fazer agora uma validação na mensagem de commit.

### Implementando commitlint no nosso projeto <a name="chapter-3"></a>

Começaremos a partir de onde estava nosso projeto (com o npm já inicializado e com o Husky devidamente instalado). Iremos então instalar a package commitlint usando o comando `npm install -g @commitlint/cli @commitlint/config-conventional`.

> Explicando o que o comando faz:
> - `npm install -g` define a instalação dessas packages de forma global na máquina.
> - `@commitlint/cli` instala o commitlint na máquina.
> - `@commitlint/config-conventional` instala uma configuração do commitlint de acordo com [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/).

Depois, com seu terminal na raíz do projeto, insira o comando `echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js`.

> Isso criará um arquivo chamado `commitlint.config.js` exportando um objeto que define que nosso commitlint deverá estar de acordo com as configurações do `@commitlint/config-conventional`.

Adicionaremos nosso primeiro hook. Com o terminal na raíz de seu projeto, insira o seguinte comando: 

```
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
```

> Na [primeira parte do tutorial](https://dev.to/marcusicaro/como-adicionar-hooks-aos-commits-de-seu-projeto-utilizando-husky-32nh), expliquei o que o comando `husky add` faz. A única diferença é que ao invés de requisitarmos que nosso hook rode um teste, estamos requisitando que o comando seja rodado sem realizar uma instalação caso commitlint não seja encontrado (`--no --`).

Como já temos o husky instalado, não será necessário instalá-lo novamente, mas, caso haja algum erro, você pode instalar o husky em seu projeto com o comando:

```
npm install husky --save-dev
```

E, por fim, ativar os hooks:

```
npx husky install
```


Vamos agora testar para ver se tudo está funcionando corretamente. Insira o comando `git add . && git commit -m 'mensagem de commit ruim'`.

O output resultante deverá ser similar a esse:

```
⧗ input: mensagem de commit ruim
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]

✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
```

Mas o que isso significa? Para entendermos, precisamos entender um pouco sobre [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0/). De acordo com conventional commit format, nossas mensagens de commit precisam ter um tipo e uma descrição, no formato <tipo>[escopo opcional]: <descrição>. No nosso caso, estamos utilizando commitlint/config-conventional, que inclui como possíveis tipos, os seguintes:

```
  'build',
  'chore',
  'ci',
  'docs',
  'feat',
  'fix',
  'perf',
  'refactor',
  'revert',
  'style',
  'test'

```

Você pode verificar isso e outras no arquivo .commitlintrc.json na raíz do projeto. O conteúdo dele deverá ser:

```
{
  "extends": ["@commitlint/config-conventional"],
  "rules": {
    "type-enum": [
      2,
      "always",
      [
        "ci",
        "chore",
        "docs",
        "ticket",
        "feat",
        "fix",
        "perf",
        "refactor",
        "revert",
        "style"
      ]
    ]
  }
}
```

> `"extends": ["@commitlint/config-conventional"]` traz as configurações de `"@commitlint/config-conventional"` e as aplica em nosso projeto.
> `"rules"` traz um objeto que pode conter algumas propriedades. No nosso caso, estamos interessados somente em "type-enum", que define algumas regras a serem utilizadas no tipo da mensagem de commit. O primeiro valor do array diz se deverá ser desabilitado (0), mostrar apenas um warning (1) ou exibir um erro no terminal (2). O segundo item do array define quando a regra deverá ser aplicada. O terceiro, são os tipos válidos.

*Nosso commit não tem um tipo válido e nem um subject (assunto).*

Agora que vimos a mensagem de erro e sabemos o que ela quer dizer, iremos consertar esse commit para ficar de acordo com as boas práticas. Iremos inserir o comando git commit -m 'feat: add commitlint to project' no terminal. O tipo é feat pois estamos adicionando uma feature nova commitlint. A descrição é o que foi feito. Depois é só salvar.

Pronto, seu commit já está de acordo com as [boas práticas para mensagens de commit](https://www.conventionalcommits.org/en/v1.0.0/) e é só fazer o push.

#### Links úteis:

- [Documentação do Husky](https://typicode.github.io/husky/)
- [Documentação do commitlint](https://commitlint.js.org/)

*Foto por <a href="https://pixabay.com/users/noname_13-2364555/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=3380550">NoName_13</a> em <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=3380550">Pixabay</a>*