Simplificando e Padronizando Commits com Conventional Commits, Commitlint e Husky
Tags: webdev, programming, tutorial, productivity
Published: 2023-08-18 17:35:44

## Introdução
Em um mundo cada vez mais voltado para o desenvolvimento ágil de software, a eficiência e a colaboração são essenciais. Uma parte fundamental desse processo é a comunicação clara entre membros de uma equipe de desenvolvimento. E é aqui que entram os Conventional Commits (Commits Convencionais) e as ferramentas auxiliares, como o Commitlint e o Husky. Neste artigo, irei discorrer como essas práticas e ferramentas podem simplificar e padronizar o processo de commits, resultando em um fluxo de trabalho mais organizado e produtivo.

## O que são Conventional Commits?
Os Conventional Commits são uma convenção simples para utilizar nas mensagens de commit. Ela define um conjunto de regras para criar um histórico de commit explícito, o que facilita a criação de ferramentas automatizadas baseadas na especificação. A ideia é que cada commit siga um formato predefinido, composto por um tipo, um escopo opcional e uma mensagem.

A mensagem do commit deve ser estruturada da seguinte forma:

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

[corpo opcional]

[rodapé(s) opcional(is)]
```

## Tipos de Commits Conventional
Os tipos de commits convencionais são a base da estruturação das mensagens de commit. Cada tipo representa a natureza das alterações feitas no código. Embora os tipos possam variar ligeiramente de projeto para projeto, aqui estão alguns tipos comuns:

- build: Alterações que afetam o sistema de construção ou dependências externas ( escopos de exemplo: gole, brócolis, npm )
- ci: Alterações nos arquivos e scripts de configuração do IC ( escopos de exemplo: Travis, Circle, BrowserStack, SauceLabs )
- feat: Indica a adição de uma nova funcionalidade ao código. Isso pode envolver novos recursos, melhorias visíveis ou qualquer mudança que agregue valor ao projeto.
- fix: Corrige um bug, problema ou erro no código existente. Geralmente, esse tipo de commit é usado para correções de funcionamento.
- docs: Refere-se a alterações na documentação, como atualizações em arquivos README, documentação interna ou comentários no código.
- style: Envolve alterações que não afetam o comportamento do código, mas sim a sua formatação. Isso pode incluir mudanças em espaçamento, formatação de código, indentação, etc.
- refactor: Indica uma modificação no código que não corrige um bug nem adiciona uma nova funcionalidade, mas melhora sua estrutura interna ou legibilidade.
- perf: Uma alteração de código que melhora o desempenho
- test: Relaciona-se a alterações nos testes existentes ou à adição de novos testes para melhorar a cobertura ou a eficácia dos testes automatizados.
- chore: Refere-se a tarefas de manutenção, ajustes no fluxo de trabalho, configurações ou outras tarefas que não afetam o código em si.

## Exemplos

### Mensagens de Commit sem Escopo

```
feat: Adicionar página de perfil do usuário
```

### Mensagem de Commit com Escopo

```
feat(lang): adiciona tradução para português brasileiro
```

### Mensagem de Commit com Corpo e Rodapé

```
fix: corrige pequenos erros de digitação no código

veja o ticket para detalhes sobre os erros de digitação corrigidos

Revisado por: Murilo Nascimento
Refs #007
```

## Commitlint: Enforce a Padronização de Commits
Mesmo entendendo o Conventional Commits nada garante que vamos respeitar as regras impostas, pois é possível que esqueçamos de seguir o padrão que foi definido. É aí que entra o commitlint. O Commitlint é uma ferramenta que ajuda a impor a convenção de commits em um projeto. Ele permite definir regras específicas para os tipos, escopos e mensagens dos commits. Ao integrar o Commitlint ele garante que todos os commits estejam em conformidade com a convenção definida.

### Instalando o commitlint

```
# Instalando o commitlint com NPM
npm install --save-dev @commitlint/config-conventional @commitlint/cli

# Instalando o commitlint com Yarn
yarn add @commitlint/config-conventional @commitlint/cli -D

# Configuração do commitlint para utilizar o Conventional Commits
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.cjs

```
Caso esteja no Windows e o comando para configuração do commitlint der erro, crie um arquivo com o seguinte nome:

- commitlint.config.cjs

E dentro dele adicione esse conteúdo:

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

## Husky: Automação de Ações no Git Hooks
Integrar o Husky ao projeto permite automatizar a execução do Commitlint e outras ações nos chamados Git hooks, que são gatilhos para a execução de scripts em momentos específicos do ciclo de vida do Git, como pré-commit, commit-msg e outros.

### Instalando o Husky

```
# Instalando o Husky com NPM
npm install husky --save-dev

# Instalando o Husky com Yarn
yarn add husky --dev

# Ativando os Hooks com NPM
npx husky install

# Ativando os Hooks com Yarn
yarn husky install

# Adicionando o Hook para disparar o commitlint com NPM
npx husky add .husky/commit-msg  'npx --no -- commitlint --edit ${1}'

# Adicionando o Hook para disparar o commitlint com Yarn
yarn husky add .husky/commit-msg 'yarn commitlint --edit $1'
```

### Testanto

```
$ git commit -m "Keep calm and commit"
⧗   input: Keep calm and commit
✖   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

husky - commit-msg hook exited with code 1 (error)
```

Os Conventional Commits, aliados ao Commitlint e ao Husky, oferecem uma abordagem sistemática para padronizar, simplificar e automatizar o processo de commits. Essa prática não apenas torna o histórico do Git mais claro e compreensível, mas também proporciona uma base sólida para automações futuras e uma colaboração mais eficiente entre os membros da equipe de desenvolvimento. Ao implementar essas práticas e ferramentas, os projetos podem desfrutar de um fluxo de trabalho mais organizado, produtivo e com menos erros relacionados a comunicação e padronização.