Publicações

Boas práticas ao escrever commits no Git

João Vitor Lima
João Vitor Lima Backend Developer

O Git é uma ferramenta bem conhecida para o controle de versões. Uma de suas principais capacidades é a de manter o registro histórico das mudanças de um projeto. Um desenvolvedor recém-chegado a um novo trabalho, por exemplo, apenas lendo os textos renderizados em seu terminal conseguirá entender as decisões técnicas tomadas pelos mantenedores como se antes estivesse sentado ao lado dos mesmos quando a decisão foi tomada.

Claro que não seria exatamente assim, por isso que esse artigo tem como foco fornecer um caminho para podermos melhorar (ou errar menos) e também relembrar a dimensão e a importância que um simples commit tem no âmbito de um projeto ou pessoa.

O que é um commit

O commit do Git representa um snapshot do seu repositório em determinado momento. Desta forma, toda mudança em um projeto é representada por um commit e todo commit, com exceção do primeiro, tem um commit "pai" que salva o estado anterior e, seguindo sucessivamente esse "pai", chegaremos ao início do projeto.

Sempre que criamos um commit precisamos gravar uma mensagem nele, e a mesma será salva no histórico do projeto permanentemente. Essa marca será acessível para todos que tenham acesso ao projeto. Futuramente, uma boa mensagem de commit sempre irá ajudar a todos que virão colaborar no projeto.

A importância de um bom commit

Todo “software” é um projeto colaborativo e até mesmo nos projetos mais isolados há uma constante mudança no desenvolvimento e decisões no projeto. Isso pode acontecer de várias formas, seja a necessidade de mudança diante de um problema, uma adaptação para o projeto adquirir novas funcionalidades ou até mesmo a mudança de mantenedores. Para cada uma dessas mudanças, as pessoas que estão atuando precisam buscar o contexto desses pequenos blocos de código aonde as mesmas devem atuar e a única maneira de salvar esse contexto de forma efetiva sem consumir horas de algum desenvolvedor ou contar com a resposta de um e-mail de algum antigo mantenedor, é que os projetos desde seu início até o fim tenham boas mensagens de commits que nos permitam acessar esse conhecimento de cada iteração de uma forma legível e organizada.

Compondo uma mensagem de commit

Visto a importância do contexto nas mudanças em cada projeto, caso quisermos deixar bem documentadas e apresentáveis, podemos tomar dois exemplos de pessoas que trabalharam em projetos onde a disciplina de commit é essencial.

Peter Hutterer, o principal mantenedor da libinput (Se você usou o mouse no Linux para acessar esse artigo pode agradecer a esse homem) conta em um artigo em seu blog:

Uma boa mensagem de commit deve responder as essas três questões sobre determinada mudança:

Por que essa mudança é necessária? A mesma pode corrigir um bug, adicionar uma feature, melhorar a performance ou a segurança.

Como a mesma resolve o problema? Para mudanças pequenas e óbvias essa parte pode ser omitida, mas a mesma consiste em uma descrição de alto nível de qual foi a abordagem usada para tratar o determinado problema.

Quais os efeitos essas mudanças tem? Além das óbvias, isso pode incluir benchmarks, efeitos colaterais, etc.

E para um exemplo mais estático, Linus Torvalds (Criador do Git e Linux) na sua pagina de contribuição para seu outro projeto Subsurface, comentou um modelo de uma boa mensagem de commit:

Cabeçalho: Explique esse commit em uma linha (Use a linguagem imperativa)

O corpo da mensagem de commit são algumas linhas de texto, explicando
em mais detalhes e possivelmente apresentando mais contexto sobre o
problema sendo tratado.

O corpo da mensagem de commit pode ser diversos paragráfos e
por favor façam corretamente a quebra de linha e mantenham as
colunas menos que 74 caracteres. Assim, o comando "git log"
irá mostrar a mensagem de forma agradavel mesma que esteja identada.

Faça questão de explicar a sua solução e por que voce está fazendo
o que está fazendo, ao invés de apenas descrever o que está fazendo de forma superficial.
Pense que revisores e o seu eu-futuro irão ler essas mudanças, mas podem não entender
por que determinada solução foi implementada.

Reported-by: quem-reportou
Signed-off-by: Seu Nome [email@host.com](mailto:email@host.com)

Conventional Commits

Acredito que os exemplos acima são mais que o suficiente para podermos dar início a essa disciplina de commit, como diz Hutterer. Porém, com o tempo, já foram desenvolvidas diversas convenções que nos apresentam um conjunto de regras fáceis de serem adotadas e que, tendo elas como base, se erguem poderosas ferramentas que irão nos auxiliar a elevar nosso patamar de desenvolvimento. A convenção que veremos nesse artigo é a Conventional Commits.

A Conventional Commits foi criada com base nas diretrizes de commit do Angular e o primeiro rascunho foi redigido em conjunto com colaboradores das ferramentas conventional-changelog, parse-commit-message, bumped, unleash e lerna.

O que essas ferramentas têm em comum? Todas trazem em alguma parte do seu fluxo alguma automação, seja gerando changelogs automáticos ou por uma mensagem de commit que define a importância de uma nova versão do pacote.

Com essa formação de base, o Conventional Commits já nasce como estandarte para ferramentas que procuram automatizar e retirar a complexidade do processo de desenvolvimento enquanto aumenta a organização do projeto.

Aqui listo as principais vantagens que ganhamos por adotar essa convenção:

Comunicar as mudanças aos colegas de equipe, ao público e demais.

A mensagem de commit deve ser estruturada da seguinte maneira:

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

    [corpo opcional]

    [rodapé opcional(s)]

E deve usar os seguintes elementos para comunicar a intenção ao leitor do commit:

fix: corrige um bug no seu código.

feat: adiciona uma nova funcionalidade no seu código.

BREAKING CHANGE: um commit que tem o texto BREAKING CHANGE no rodapé do commit ou usa um ! depois do tipo/escopo, introduz uma grande mudança no código.

Exemplo:

chore!: remove suporte ao Node 14

Para suportar novas funcionalidades que vão
agregar mais desempenho a aplicação como o
`Promises.any` estamos subindo o requerimento
mínimo do projeto.

BREAKING CHANGE: a versão minima do Node agora é a 16.

Outros tipos além do fix: e feat: são permitidos, como, por exemplo: ⁣

  • chore: Mudanças de configuração ou de código que não entra em produção;
  • ci: Alteração em algum arquivo de CI do projeto;
  • docs: Mudanças na documentação;
  • style: Alteração apenas no estilo do código, sem mudança de algoritmo;
  • refactor: Refatoração de determinado bloco de código;
  • perf: Alterações que impactam o desempenho da aplicação;
  • test: Mudanças na estrutura ou na forma de testar o projeto.

Exemplo:

docs: adiciona stack de Pyhon e Ruby a documentação
    
Atualiza a tabela de "detalhe das stacks" com as
ferramentas PyLint para Python e RuboCop para Ruby 

ref #12

Facilite para as pessoas contribuírem com seus projetos

Imagine que você é um desenvolvedor que vai ajudar a manter um projeto mais antigo, quando você rodar o comando git log qual das imagens abaixo você gostaria de se deparar?

Inconvetional Commits

Ou

Com Conventional Commits

Um commit bem estruturado facilita o trabalho de leitura e atuação de todos que pretendem colaborar com um projeto. Não e atoa que grandes projetos colaborativos sempre priorizam o uso de mensagens bem estruturadas.

Com base nos commits estruturados, automatize o aumento da versão semântica

Podemos usar o projeto semantic-release para automatizar o lançamento de versões do nosso pacote conforme a mensagem de commit. A automação é bem simples. Através da mensagem de commit, o semantic-release define que incremento ele deve fazer conforme a imagem abaixo:

Semantic Release

Isso nos permite atualizar consistentemente os nossos pacotes de maneira muito rápida e organizada o que nos salva muito tempo.

Gere de forma automática changelogs aos seus projetos

E para colocar a cereja no bolo, podemos gerar um changelog completo e formatado conforme as mensagens do projeto usando o conventional-changelog. Com essa ferramenta, podemos fechar um ciclo de publicação apenas com o poder de uma mensagem de commit bem estruturada!

Como não errar!

Se escolhermos seguir o Conventional Commits é possível impor de forma definitiva no nosso código o mesmo.

Podemos impedir que enviemos commits que não atendem as especificações da convenção com o Commitlint e assim extrair o máximo das vantagens apresentadas acima.

Commitlint

Esse é um projeto com uma premissa muito objetiva. O Commitlint simplesmente verifica se o seu commit atende as especiações da convenção. O interessante é que é possível configurar um hook pré-commit usando o husky , desta forma, sempre que terminarmos o commit, ele irá informar se houver erros da mensagem e não irá fazer o commit caso tenha.

Vejamos como configurar o Commitlint:

yarn add --dev @commitlint/{config-conventional,cli}
# Usa regras do Conventional Commits
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

Configure o Pre-Hook do Git com o Husky:

yarn add husky --dev
yarn husky install
yarn husky add .husky/commit-msg 'yarn commitlint --edit $1'

Agora tente errar o commit para testar:

git commit -m "ajuste"              
yarn run v1.22.17
$ /home/joao/Documents/projetos/pipelinit-sample-vue-html/node_modules/.bin/commitlint --edit .git/COMMIT_EDITMSG
⧗   input: ajuste
✖   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

Pronto!

Considerações finais

Os nossos commits conseguem interferir com nossos colegas de equipe do presente e futuro, e estão presentes no desenvolvimento de cada mudança no projeto. Desta forma, se faz necessário que os projetos cada vez mais tenham padrões de contribuição e mensagens de commits bem definidos e organizados.

Com a evolução nos métodos de organizações de projetos, algumas convenções apresentam uma nova visão para os commits no qual integram a eles a possibilidade de completar o fluxo de desenvolvimento da primeira mudança até a publicação e divulgação do pacote de maneira completamente automatizada, rápida e fácil.

Esperamos que você possa seguir algumas das ideais apresentadas e que ajude a fomentar melhores padrões de commits em seus projetos. Acreditamos que o resultado seja uma melhor colaboração por todos que estão dispostos a trabalhar de maneira séria, produtiva e eficiente.

Referencias

Solução de problemas, melhoria de gestão e aumento de produtividade

Com tecnologias renomadas, aplicamos práticas ágeis e capacitamos sua equipe.

Fale com um consultor