Git é uma ferramenta de versionamento de código, isto é, realiza “fotos” de partes de seu código e montando uma linha do tempo conforme há alterações em partes dele. Conforme você evolui nos conceitos e já está dominando os comandos básicos (git pull, add, commit, push) na prática, percebe alguns problemas inerentes do Git: falta de padronização nas mensagens de commits e problemas ao trabalhar colaborativamente, mais especificadamente quando você trabalha em uma equipe. Esse artigo irá abordar esses problemas, algumas sugestões de soluções e ferramentas para você melhor trabalhar com o Git em projetos em grupo do seu trabalho ou open-source.
Boas práticas de escrita de commit
Essa é uma tirinha do Xkcd, mostrando um problema clássico das mensagens de commit do Git: conforme o tempo passa e há mais modificações no projeto (e assim mais commits), menos legíveis e informativas as mensagens são. Isso é um problema pois as mensagens dos commits são de extrema importância para o entendimento das modificações no código, por que e onde foram realizadas, sendo ruim e pouco prático para um revisor de código ter que “abrir” o commit e visualizar o código alterado para entender as modificações feitas, principalmente em um projeto grande e assim com muitos commits.
Assim, com o passar do tempo, foram sendo criados algumas boas práticas de commit a serem implementados em projetos, principalmente quando há uma equipe trabalhando, ou o projeto é (ou irá se tornar) open-source.
Commitar códigos completos e pequenos
Uma primeira boa prática é em relação ao tamanho e quantidade de alterações que você irá acumular para colocar em um só commit. Na teoria, você pode colocar um dia inteiro de trabalho em um só commit, alterando +1000 linhas em +10 arquivos diferentes. Consequentemente sua mensagem de commit ficará extremamente grande (que é um problema a ser tratado no futuro desse artigo) ou extremamente genérico. Outro problema é, se tiver a necessidade de revisar o código ou alterar a linha do tempo dos commits, muitas alterações poderão ser perdidas, mesmo elas podendo ser importantes.
Assim, o ideal é pensar o que irá entrar no próximo commit a ser realizado, e não misturar diferentes objetivos em um commit. Por exemplo: tenho uma tarefa de resolver um bug no botão do login. Resolvendo-o, faço o commit: “fix login button bug” (corrige bug do botão no login). Essa alteração terá, provavelmente, poucos arquivos alterados e não irá misturar outras tarefas (como arrumar a cor de fundo do login). É uma ideia subjetiva, mas conforme você vai praticando, cada vez vai ficar mais claro para fazer commits “menores”.
Fazer boas mensagens de commits
A estrutura de uma mensagem de commit é: descrição/subject, corpo/body e um rodapé/footer. Algumas boas práticas de mensagens de commits, principalmente na escrita da descrição/subject são:
- Escrever tudo em inglês → É considerada uma língua internacional, e utiliza-lá padroniza as mensagens, facilitando a todos da equipe atual e futuros contribuidores. Se houver um caso em que a equipe não sabe inglês, pode fazer em português (ou outra língua), sendo o ideal não misturar 2 línguas, por exemplo: “fix cor botão para red”.
- Usar o imperativo → Usar verbos no imperativo, principalmente em sua descrição/subject. Elas dão uma ideia de comando e instrução, por exemplo: “Update call to action button style on homepage” e “Add anchor on products page”.
- Fazer um commit curto → Para apresentar um commit, um texto curto e direto na descrição/subject do commit é o ideal. Existe a parte do corpo/body de um commit, onde você pode explicar com mais detalhes as mudanças realizadas.
Conventional Commits
O Conventional Commits é uma especificação com o objetivo de padronizar e dar um significado maior para as mensagens de commit, seguindo um estrutura fixa e regras. Ela se encaixa com o SemVer (Semantic Versioning, padronização dos números de versão de projetos em MAJOR.MINOR.PATCH). A estrutura do Conventional Commits é:
<tipo>(<escopo opcional>): <descrição>
<corpo opcional>
<rodapé opcional>
Explicando a estrutura, temos:
- Tipo → Primeira parte da mensagem de commit, onde informa qual o tipo do commit. Pelo Conventional Commits, são: feat (feature, quando há a adição de novas funcionalidades), fix (quando há a resolução de problemas/bugs), Pela Convenção do Angular, há outros tipos: build, chore, ci, docs, style, refactor, perf, test. O tipo é sempre seguido de : (dois pontos) e depois um espaço em branco.
- Escopo → É o contexto do commit, normalmente escreve-se qual arquivo/bloco de código principal foi alterado. Ex: uma alteração no README pode se escrever no escopo:
readme
. - Descrição → É a descrição da mensagem do commit, onde se tem a ideia principal explicada resumidamente, aplicando as regras acima.
- Corpo → É onde há a explicação mais detalhada do commit. É espaçada por 1 linha em branco em cima e embaixo dela.
- Rodapé → Local de informações adicionais, como Breaking Changes (mudanças de versões), resolução de issues pelo commit, nomes de revisores.
Ferramentas
Existem ferramentas que facilitam na escrita e padronização das mensagens de commit, e elas são muito úteis para não precisar ficar decorando regrinhas e escrever com mais velocidade. Aqui irei listar 3 “ferramentas” de linha de comando, mas existem também ferramentas/widgets para o VSCode, Github Desktop, Gitkraken, etc.
Commitizen-CLI
A primeira ferramenta é o Commitizen-CLI. Ele usa uma CLI (interface na linha de comandos) para facilitar a escrita de commits seguindo o padrão do Conventional Commits. Depois de instalá-lo, em vez de digitar git commit -m "sua mensagem"
como normalmente todos fazem, digite git cz
, abrindo uma interface que você irá escolher o tipo, escopo, descrição, corpo e rodapé do commit, criando, no final, a sua mensagem de commit já formatada.
Commitlint
O Commitlint é um linter (analisador de código, que busca erros e bugs) para te “obrigar” a seguir a formatação do commit do Conventional Commits. Quando você escreve uma mensagem que não está seguindo a estrutura mínima do Conventional Commits (tipo: descrição
), ele bloqueia seu commit e informa quais erros ou partes estão faltando para a padronização correta. Isso ajuda bastante para evitar que haja commits “errados” no histórico, facilitando na padronização de todo o time.
Git Hooks
Git hooks é uma funcionalidade nativa do Git. Você pode encontrar sua pasta com arquivos de exemplo em .git/hooks
. A ideia dele é de scripts que o Git executa automaticamente antes ou depois de eventos do Git, como: commit e push. Alguns exemplos são:
- post-merge → realizado após o
git pull
- pre-commit → realizado antes do commit
- commit-msg → verifica a mensagem do commit
- pre-push → realizado antes do
git push
Para cada um desses hooks, pode se realizar tarefas, como rodar comandos, testes, de forma automática. Por exemplo, rodar o commitlint para analisar a mensagem de commit, utilizando o hook commit-msg
. Adicionalmente, existem o Husky, que é uma ferramenta que facilita na hora de criação e gerenciamento de Git hooks, por rodar em cima de Node.js.
Essas regras e ferramentas são bem importantes a serem aplicadas no início de um projeto, assim todos da equipe já configuram e seguem as boas práticas de mensagem de commit do Git. Em Outubro de 2021, realizei uma palestra explicando e aplicando essas e outras ferramentas, além de mostrar na prática as diferenças de um commit “simples” para um que aplicava essas regras. Pode assistir aqui: https://bit.ly/MinicursoGIT-ICMCJunior, e o material está aqui: https://bit.ly/MaterialMinicursoGIT
Gostou do artigo? Não se esqueça de visitar nosso blog, compartilhar com os amigos e nos seguir nas redes sociais. Até a próxima!