Entendendo padronização de commits (Conventional Commits)
Tags: git, github, braziliandevs, tutorial
Published: 2022-05-23 14:32:36

#Motivação
A um tempo venho pesquisando sobre o tema de padronização de commits e olhando ferramentas para facilitar o uso (coisa que vou apresentar mais a frente).E recentemente participei de uma palestra rápida do [Ivan Rosolen](https://www.linkedin.com/in/ivanrosolen/) sobre o tema e isso me fez querer compartilhar o conhecimento que adquiri com muita pesquisa. Muitos dos conteúdos trazidos aqui foram encontrados na apresentação do Ivan.

#O que é **Padronização de Commits**
Essa padronização veio para solucionar um problema que muita gente encontra ao fazer uma revisão de um PR (pull request), ou quando se entra em uma empresa ou squad novo e tenta entender o que foi feito no fluxo de trabalho do Git.

> Trate o git como uma ferramenta de comunicação e não de armazenamento de código
De Jair Henrique no Twitter

Como a frase acima propõe, o git deve ser um storytelling de como a aplicação está no momento para que qualquer um que veja e entenda o que foi feito, mesmo não sendo da área. 

Utilizando essa padronização é muito mais simples de uma pessoa nova no projeto entender o que foi feito e a comunicação entre a equipe fica muito mais fluida e assertiva.

Essa padronização começou sendo criada pelos usuários de Angular, mas pode ser aplicada a qualquer linguagem.

![Imagem mostrando histórico de uma aplicação usando padronização de commits](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2cw36k091mmyt0a7jcxc.png)
 
A imagem acima mostra um histórico de uma aplicação usando padronização de commits, que por acaso é do [repositório](https://github.com/conventional-commits/conventionalcommits.org) da iniciativa.

#Vantagens
- Ao utilizar o padrão, se evita commits muito vagos que não se explica a alteração;
- Comunica a mudança feita na aplicação para as pessoas da equipe, e para qualquer outra pessoa interessada com objetividade e assertividade;
- Descreve o motivo da alteração ou correção do código;
- Facilita a contribuição de outras pessoas ao projeto.
- Facilita o versionamento semântico e criação de CHANGELOG.

#Estrutura

```
<tipo>[escopo opcional]: <breve descrição>

[corpo (opcional)]

[rodapé opcional]
```

O **tipo** segue uma lista predefinida que pode ser modificada de acordo com o projeto ou organização que utiliza.

Os tipos são descritos mais a frente.

O **escopo** é a funcionalidade ou contexto da aplicação.

A **descrição** deve ser uma descrição sucinta da mudança.
- use o imperativo, tempo presente: "mudança" não "mudou" nem "muda"
- não capitalize a primeira letra
- sem ponto (.) no final

O **corpo** é a descrição do que foi feito detalhadamente. 

O **rodapé** é usado para links de referência como issues do gitHub, tikets do Jira, etc.

#Tipos
**build**: São alterações que afetam o sistema de build do projeto ou dependências externas.
**chore**: São alterações em arquivos que não influenciam no código de produção da aplicação, ou seja, nada que o usuário final veja. Como alterar um arquivo `.gitignore`, `package.json`, etc.
**static**: São alterações no conteúdo de arquivos estáticos como dados `.json`, imagens, etc.
**cd**: São alterações em nossos arquivos e scripts de configurações para CD (entrega contínua).
**ci**: São alterações em nossos arquivos e scripts de configurações para CI (integração contínua).
**docs**: São alterações ou criação de documentação.
**feat**: Um novo recurso.
**fix**: Uma correção de bug da aplicação.
**improve**: Uma alteração de código que melhore o comportamento de um recurso.
**perf**: Uma alteração de código que melhore o desempenho ou performance.
**refactor**: Uma alteração que não corrige um bug nem adiciona um novo recurso, só refatora o que já foi feito.
**style**: Alterações que não afetam o significado do código só alteram um espaço em branco, formatação, ponto e vírgula, etc.
**revert**: reverter para um commit anterior
**test**: Adiciona testes ausentes ou corrige testes já existentes.

Para mais detalhes veja a [documentação oficial](https://www.conventionalcommits.org/pt-br/v1.0.0/).

##Os tipos mais utilizados no dia a dia
- feat
- fix
- refactor
- improve
- test

##Exemplo de um commit seguindo o padrão

![Imagem de um commit seguindo o padrão](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no00kj2z5kyttmqzhddt.png)
*Essa imagem foi retirada da apresentação do Ivan que está referenciada ao final.
 

#Ferramentas para facilitar o uso

**Obs:** Como última ferramenta mostro uma extensão para VSCode que facilita tudo o que essas ferramentas a seguir fazem.


Aqui vou mostrar como instalar e usar algumas ferramentas muito legais que eu uso desenvolvendo em JavaScript, que são:

- [CommitLint](https://github.com/conventional-changelog/commitlint)
- [Husky](https://typicode.github.io/husky/#/)
- [Commitizen](https://github.com/commitizen/cz-cli)

## Para que cada um serve?
O **CommitLint** é uma ferramenta que verifica se seu commit está seguindo o padrão da estrutura, como vimos acima. Ele utiliza o **Husky** para verificar seus commits antes de serem finalizados. O Husky gera um script que intercepta seu commit, passando ele para o CommitLint para ser verificado. 
Caso seu commit não siga os padrões, ele é rejeitado e retorna uma mensagem de erro sobre seu commit.
O **Commitizen** é uma ferramenta de automação que te ajuda a estruturar seu commit de forma mais simples, agindo como perguntas e respostas. Primeiro pergunta qual o tipo de alteração, escopo, descrição, corpo, se houve uma breaking change, e por fim se afeta uma issue que é no rodapé.

A imagem abaixo mostra um exemplo de uso do Commitizen em paralelo ao CommitLint e Husky.

![Imagem mostrando um exemplo de uso do Commitizen em paralelo ao CommitLint e Husky](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clkoocn89thbjspsr6os.png)
 

Para instalar essas ferramentas, entre em seu projeto e faça os seguintes passos:

**Lembrando**: qualquer problema na instalação, entre na página oficial do repositório e siga os passos ditos por lá.

1 - Instale o CommitLint

```
npm install -D @commitlint/{config-conventional,cli}

echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

```

2 - Instale o Husky e ative os hooks
```
npm install -D husky

npx husky install

cat <<EEE > .husky/commit-msg
#!/bin/sh
. "\$(dirname "\$0")/_/husky.sh"

npx --no -- commitlint --edit "\${1}"
EEE

chmod a+x .husky/commit-msg
```
Nesse momento, se você tentar fazer um commit que não siga o padrão, ele será rejeitado.

3 - Instale o Commitizen
Primeiramente você deve deixar seu repositório preparado para receber o Commitizen

```
npm install commitizen -g

commitizen init cz-conventional-changelog --save-dev --save-exact
```
Em seu arquivo `package.json` adicione:
```
 "config": {
    "commitizen": {
      "path": "cz-conventional-changelog"
    }
  }
```

Pronto!
Agora é só digitar `git cz` ou apenas `cz` e o Commitizen abrirá para você estruturar seu commit padronizado.

##Melhor para o final!

Existe uma extensão chamada [Conventional Commits](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits) para o VSCode que simplesmente facilita a vida ao utilizar o padrão, pois ele estrutura completamente seu commit. 
No link acima, tem toda a descrição e forma de utilização da extensão.


#Referências
[Conventional Commits por Ivan Rosolen](https://speakerdeck.com/ivanrosolen/conventional-commits?slide=24)