O que você realmente precisa saber sobre commit semântico

Antes de falarmos sobre o que você realmente precisa saber sobre commit semântico, eu quero te fazer uma pergunta: por que você versiona o seu código? Se você não conseguir responder a essa pergunta, jamais entenderá e aplicará commit semântico (ou conventional commits) de maneira eficaz. Neste post quero te explicar do que se trata. E em um próximo post, vamos aprender a como automatizar esse processo.

Por que versionar o código?

Algumas pessoas encaram o versionamento de código como uma forma de guardar o código e não perder. Ou ainda, deixá-lo acessível as pessoas desenvolvedoras e garantir uma forma fácil de integração. Se esse fosse o único trabalho de um versionador de código, o git e o mercurial seriam facilmente substituíveis por arquivos zipados e um mecanismo de comparação de código. Versionamento é muito mais do que isso, e deixa eu usar um exemplo pra te explicar:

Você já deve ter passado por uma situação em que estava usando o bom e velho método do teste x falha. E chegou aquele momento em que você conseguiu! Tudo funciona! Mas no caminho você fez tantas alterações que não consegue definir qual foi a variação do código que realmente solucionou o problema. Então você vai desfazendo uma a uma. Até que remove uma alteração e… opa! Era ela! Você adiciona a funcionalidade de novo, esperando que a aplicação se comporte corretamente e pimba! Erro também! E agora? Seria legal recomeçar lá de onde as coisas funcionavam normalmente. Você pode dar trocentos CTRL+Z até alcançar o código funcional ou… navegar para a versão em que o código funcionava.

Versionadores como o Git permitem que você tire uma fotografia das alterações feitas no código a cada commit. E se caso você queira voltar num momento específico, basta fazer o checkout daquela versão do seu código! Parece algo bem óbvio para ser dito, mas a verdade é que a maior parte das pessoas esquece disso e apenas navegam pelas branches. Quem age assim, trata o versionamento como “armazenamento de arquivos” apenas e não um controle de versão.

Então a primeira lição é: A cada commit nós estamos criando uma versão do nosso código.

Fotografias contam histórias

Minha família sempre gostou muito de fotos. Meu avô, caminhoneiro, sempre andava com uma câmera e um filme 24 poses pra tirar fotos das suas viagens. A gente sabia onde cada foto tinha sido tirada e a história por trás dela. Até que a memória começou a trair a gente. Meu avô e vó discutiam sobre onde algumas fotos foram tiradas e o motivo por trás do clique. E foi assim que a gente passou a escrever atrás de cada foto a data, local e um resuminho da história por trás dela. No Natal, quando a gente se reunia, era só olhar a foto e ler o verso.

Se você está versionando o seu código, mas não sabe o que cada versão guarda, você está fazendo trabalho de tolo. Na nossa área, principalmente onde o turn over é tão grande, ter boa documentação é fundamental. E a melhor documentação sempre será o código – ou o que estiver mais próximo dele. Não precisamos de muito tempo para que todo um time seja substituído. E aí? porque tem essa branch solta aqui? Por que parece que recomeçaram todo o código? O que levou a essa determinada decisão?

Ao olhar o histórico do Git – ou de qualquer outro versionador – você e todas as pessoa devem saber: O que aquele commit adicionou no sistema, porque foi adicionado e porque foi feito daquele jeito. Principalmente se algo fora do comum foi feito. Outra questão desejável é que, caso você utilize um board ou qualquer tipo de controle de tarefas, qual a tarefa que aquele código está cumprindo. E se tiver um link para ele é ainda melhor, mas não obrigatório. Afinal, os boards até podem partir. Mas o código? Esse fica.

Commit semântico?

E como tudo que é importante para o mercado, já foi construído, pela comunidade, um padrão. Chama-se Commit Semântico, ou Conventional commits. Basicamente, é uma mescla entre conjunto de palavras-chave associada a uma formatação textual utilizada no seu commit. Você pode criar o seu próprio esquema de palavras chaves, mas aconselho que você fique próximo (ou não se distancie) da especificação feita pela comunidade Angular.

O formato do commit semântico, você pode conferir nos links acima com maiores detalhes. Mas um commit bem básico seria algo como:

feat: Adiciona a feature XPTO

Com a feature XPTO, usuário será capaz de fazer uma coisa que ele não conseguia fazer antes.
Optamos por utilizar esse recurso estranho por causa dessa necessidade em particular.

Refs #888

Se a feature RPX causar uma quebra de retro compatibilidade, você poderia escrever assim:

feat: adiciona uma feature RPX

RPX existe que uma restrição de dependência seja violada

BREAKING CHANGE: Aqui eu digo porque quebra a compatibilidade.

Refs #999

Percebe como o commit conta a história do código? Você não precisa ir muito longe para compreender o que passava pela cabeça das pessoas que escreveram o sistema. Está ali, no comentário do commit. Se quiser mais detalhes de implementação, basta abrir o diff do código. Está tudo lá. Quer detalhes de negócio? Saber se foi testado ou não? Você pode ver o número da história no próprio commit. E se o ambiente que você visualiza os commits suporta markdown, você pode até criar hiperlinks no commit (tá, acho exagerado mas… você que sabe).

Os tipos de commit:

Além do tipo feat, também existem outros tipo:

  • build: Para quando você está alterando algo relativo ao build da sua aplicação. Por exemplo: Adicionou um dependência no package.json? Configurou o husky no seu projeto? Criou um .sh que faz o build e extrai a cobertura de código? Utilize esse tipo de commit;
  • ci: Todas as modificações que impactem no seu processo de CI/CD. Como a manutenção de pipelines, por exemplo;
  • docs: Quando alterar a documentação do projeto (seja ADR ou até mesmo adição de comentários);
  • feat: features;
  • fix: arrumou um bug?
  • perf: melhorias voltadas a performance;
  • refactor: sabe quando você adiciona o ESLint e surgem mil warnings e hints pra retirar? É esse cara que você vai utilizar;
  • style: Muito parecido com refactor, mas é mais voltado para code style do que pra limpeza de código.
  • test: quando você faz testes de unidade;

E quando eu tenho mais que um tipo de código no mesmo commit?

Eu poderia chamar isso de “commit smell”. É uma “ótima prática” que você sempre faça commits pequenos (mesmo aqueles que são locais) e que você abra Pull Requests pequenos também. Os commits locais pequenos porque, caso você queira desfazer alguma coisa, você quer desfazer só aquela uma coisa, e não quinze que estão juntas, amontoadas no mesmo commit.

Já o tamanho do Pull Request é uma questão de respeito com a pessoa que revisa o código. Muito código exige uma carga cognitiva muito grande. E via de regra, PR grandes não são bem revisados. Imagine que você apenas moveu os arquivos de uma pasta para outra – para atender um padrão de design de código. E pra “economizar PR”, você também fez alterações de negócio no código. Como seria possível revisar isso? E ainda que fosse possível a revisão, como encontrar o ponto que foi realmente alterado no meio de 300 arquivos?

Seja profissional e organize bem o seu trabalho e a estratégia de desenvolvimento ANTES de começar a desenvolver. Cada Pull Request deve ter apenas um assunto. Precisa alterar os arquivos de lugar? Abra um PR só com isso. Precisa rodar um lint no seu código? Abre um PR apenas disso. E utilize o tipo de commit mais adequado.

Importante: utilize sempre APENAS UM tipo por commit. Você escreveu um commit que arruma um erro que não foi pra produção ainda? Faça junto com um PR de nova feature que tá tudo bem. Agora, você arrumou um bug que já está em produção? Pode ser legal você documentar isso, abrindo um PR exclusivo pra essa situação.

Boas histórias precisam ser contadas

A essa altura você já deve ter percebido que há uma possível aproximação entre o Versionamento Semântico (o SemVer) e os Commits Semânticos. Existem processos que possibilitam a automatização do versionamento, baseado no conteúdo que você está commitando (nas mensagem de commit). Mas essa ligação conta apenas parte da história. Outro lugar, muito mais amigável ao usuário, onde história reside é no CHANGELOG.

Ter change logs é interessante também para ter uma documentação do sistema, que não esteja apenas atrelada ao Git. Talvez você queira disponibilizar isso para o usuário final de alguma maneira. “Quero ver se o meu card “#999″ foi incluído nessa versão”. Ele abre o changelog (ou release notes) e vê lá o seu card. Se você faz isso manualmente, eu sinto muito. Com os commits semânticos é totalmente possível automatizar esse processo na construção da sua release. Quer descobrir como? Não perca o próximo post sobre Como automatizar a geração de Changelog.

One thought on “O que você realmente precisa saber sobre commit semântico

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.