Padronização de commits em projetos Typescript
Tags: git, node, tutorial, typescript
Published: 2022-08-08 03:54:00

## Porque escrever uma boa mensagem de commit?

Mensagens de commit servem para comunicar o motivo da adição, remoção ou alteração de um determinado trecho de código. Boas mensagens de commit são uma ótima documentação para um projeto, elas podem servir como um histórico de como o código foi construído e evoluiu ao longo do tempo, ter isso em mãos pode ser muito útil em algumas situações onde estamos tentando entender decisões arquiteturais ou como alguma funcionalidade foi implementada.

## Mas como escrever boas mensagens de commit?

A melhor forma de escrever uma mensagem de commit é seguindo um determinado padrão, um dos padrões mais conhecidos é o [conventional-commits](https://www.conventionalcommits.org/en/v1.0.0/#summary), uma especificação focada em versionamento semântico que tem o intuito de propor mensagens de commit mais informativas o possível.

## Padronizando commits em um projeto Typescript

Para usarmos padronização de commits em nossos projetos temos de fazer uso de uma funcionalidade do git que permite executar um determinado script quando algumas ações ocorrem, chamamos essa função de [hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_git_hooks), os tipos mais comuns de hooks são:

* `pre-commit`: é o primeiro hook a ser executado, ou seja, ele é executado antes mesmo da escrita da mensagem de commit, com ele podemos analisar o que está para ser "commitado", ou seja, podemos analisar todo o código que foi adicionado com o comando `git add`. É o hook ideal para rodar _linters_ como o eslint, por exemplo.

* `prepare-commit-msg`: é um hook que é disparado antes do editor de mensagens de commit ser executado, aqui podemos definir o padrão da nossa mensagem de commit.

* `commit-msg`: é um hook que recebe um parâmetro que é o caminho do arquivo com a mensagem de commit escrita pelo usuário, um script é executado usando esse arquivo como referência, como ele podemos validar se a mensagem foi escrita corretamente.

* `post-commit`: hook executado quando todo o processo de commit foi concluído, geralmente é usado para notificação ou algo similar.

* `pre-push`: vai ser executado durante o `git push`, depois das validações de referências remotas (se o repositório realmente existe, por exemplo), mas antes de qualquer objeto ser transferido, muitas vezes utilizado para executar testes unitários do projeto.

## Instalando e configurando ferramentas

As ferramentas utilizadas serão:

* husky: permite criar hooks no git de maneira simplificada
* commitlint: permite validar nossas mensagens de commit
* lint-staged: executa um script em arquivos que estão na staged area
* commitizen: é uma ferramenta de linha de comando que pode ser utilizada para auxiliar na criação das mensagens de commit.

### Instalando, configurando e criando primeiro hook

##### lint-staged

Para instalar o lint-staged temos de executar o comando `npm install lint-staged --save-dev` que vai salva-lo como dependência de desenvolvimento. O lint-staged precisa saber qual comando será executado e em que código, para isso ele usa um arquivo que deve estar no diretório raiz da aplicação chamado *.lintstagedrc.json*, como queremos executar o nosso linter em todos os nossos arquivos typescript do projeto temos de colocar a seguinte configuração dentro desse arquivo:
```json
{
  "*.ts": ["npm run lint"]
}
```
##### commitlint

Para instalar o commitlint temos de executar o comando `npm install @commitlint/{cli,config-conventional} --save-dev` e para a sua configuração, assim como o lint-staged, vamos precisar de um arquivo dentro do diretório raiz do projeto, esse arquivo pode ter distintos nomes e extensões:

* _commitlint.config.js_
* _.commitlintrc.js_
* _.commitlintrc_
* _.commitlintrc.json_

E temos de popular esse arquivo com o tipo de convenção que estamos utilizando nas nossas mensagens de commit, para isso podemos executar o seguinte comando: `echo "{'extends': ['@commitlint/config-conventional']}" >> .commitlintrc`, esse comando cria um arquivo devidamente populado com o padrão utilizado nos nossos commits.

##### Husky

Para instalar o husky usamos `npm install husky --save-dev`, após a instalação temos de habilitar a criação de hooks e para isso usamos o comando `npx husky install`, após executar esse comando será criado um diretório _.husky_ onde ficarão os nossos arquivos de script de hooks. Para termos os hooks disponíveis temos de executar `npm pkg set scripts.prepare="husky install"`, assim teremos dentro de _package.json_:

```json
// package.json
{
  "scripts": {
    "prepare": "husky install"
  }
}
```
#### Criando primeiro hook

O primeiro hook que vamos criar é o de `pre-commit`, ele vai ter a função de formatar código que está na nossa staged area, para criar o hook executamos o seguinte código:

`npx husky add .husky/pre-commit "npx lint-staged"`

O comando `npx lint-staged` vai ser responsável por executar o comando `npm run lint`, que foi estabelecido dentro do array no arquivo _.lintstagedrc.json_. 

Agora temos um arquivo _pre-commit_ dentro do diretório _.husky_ e o seu conteúdo:

```zsh
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
```

##### commitizen

Para instalar o commitizen usamos o seguinte comando: `npm install commitizen --save-dev` e temos também de inicializar a especificação do conventional-commits e para isso temos de executar: `npx commitizen init cz-conventional-changelog --save-dev --save-exact`, como o commitizen é a ferramenta de linha de comando que vai ser executada antes de termos uma mensagem de commit temos de adicionar o hook `prepare-commit-msg` para a sua execução, assim sendo temos: 

`npx husky add .husky/prepare-commit-msg "exec < /dev/tty && npx cz --hook || true"`

Esse comando vai fazer com que o terminal abra uma ferramenta de linha de comando onde é possível escolher o tipo de modificação que está sendo feita e também escrever uma mensagem apropriada para a modificação que está sendo commitada.

![commitizen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u92ni6aj163fxkz67zxk.gif)
 

#### Criando hook para a mensagem de commit

Agora que temos os dois hooks anteriores ao commit já criados, temos de criar um hook que vai ser utilizado para a mensagem escrita, aqui vamos validar se realmente a mensagem está como deveria estar. Executando o comando:

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

O objetivo desse hook é analisar o commit escrito, e se ele realmente segue os padrões estabelecidos na convenção escolhida. Se a mensagem não foi escrita adequadamente temos a seguinte saída:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/37tge84ozunkdl5r5iij.png)