Simplificando o controle de versão com Conventional Commits

Simplificando o controle de versão com Conventional Commits

Imagine que você está fazendo uma limpeza em seu computador. É preciso retirar cada peça, limpá-la e, em seguida, recolocá-la em seu devido lugar. Você desliga a fonte, retira a placa de vídeo, SSD, desconecta as memórias, etc. Durante esse processo, você resolve anotar cada etapa para lembrar quando for montar novamente o computador. Afinal, você não quer encontrar alguma surpresa desagradável quando for ligá-lo novamente.

Imagem: Ao topo a legenda: “ Quando você decide limpar o seu PC, mas agora não liga mais”. Abaixo da legenda uma criança chora com uma chave de fenda na mão direita, enquanto olha para o seu computador que aparentemente não quer funcionar.

Agora, aplique essa mesma ideia à criação de software, onde cada alteração no código é uma etapa importante. Será muito mais fácil se, durante a criação do seu software, você tiver documentado de alguma forma cada uma das alterações importantes que fez nele.

É aqui que entra a especificação do Conventional Commits, uma metodologia poderosa para criar um histórico de commit explícito, simplificando a sua vida e dos desenvolvedores que verão sua aplicação, além, de facilitar a colaboração em equipe.

Por isso, neste artigo você aprenderá:

  • O que são Conventional Commits;
  • Qual problema eles resolvem;
  • Como utilizar na prática essa especificação para melhorar suas mensagens de commit;
  • Porque usar Conventional Commits no desenvolvimento de suas aplicações.

Vamos nessa?

O Desafio do Controle de Versão

Ao desenvolver um software, uma das partes mais críticas é o controle de versão. Como manter um registro claro de todas as alterações feitas no código? Como comunicar essas mudanças de forma eficaz para sua equipe e para outros interessados no projeto? É aqui que entra a especificação do Conventional Commits.

Banner promocional da Alura, com um design futurista em tons de azul, apresentando o texto

Mensagens de Commit Confusas

Antes de explorar como a especificação do Conventional Commits pode ajudar, é importante entender o problema que ele resolve. Imagine que você está trabalhando em um projeto com várias pessoas, e cada uma delas escreve mensagens de commit a sua própria maneira. Algumas são vagas, outras são detalhadas demais, e muitas não seguem um padrão. Isso pode levar a confusões, dificultando a compreensão das alterações e a criação de um histórico de commit organizado.

A especificação do Conventional Commits oferece uma solução elegante para esse problema. Ela define regras simples para criar mensagens de commit estruturadas da seguinte forma:

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

[corpo opcional]

[rodapé(s) opcional(is)]

Aqui está uma explicação mais detalhada dos elementos:

  • <tipo>: o tipo de commit, que descreve a natureza da alteração (por exemplo, feat para adicionar um novo recurso ou fix para corrigir um problema);
  • [escopo opcional]: uma descrição opcional do escopo da alteração, fornecendo contexto adicional;
  • <descrição>: uma breve descrição das alterações feitas;
  • [corpo opcional]: informações contextuais adicionais sobre as alterações;
  • [rodapé(s) opcional(is)]: informações adicionais, como referências a problemas, revisores, ou uma seção crucial chamada BREAKING CHANGE para indicar mudanças que quebram a compatibilidade.

Agora que você compreendeu a estrutura das mensagens de commit no Conventional Commits, é o momento de explorar os tipos de commit de forma mais detalhada. Vamos lá!

Tipos de Commit

O campo <tipo> desempenha um papel fundamental na comunicação da intenção por trás de cada alteração feita no código. Então, para melhorar nossas mensagem usando o Conventional Commits, vamos dar uma olhada em alguns dos tipos de commit mais comuns e como eles podem ser utilizados em seus projetos:

  • build:
    • Uso: esse tipo de commit é apropriado para quando você faz alterações no sistema de compilação ou nas dependências externas do seu projeto, como: adicionar, remover ou atualizar dependências.
    • Exemplo: build: Atualizar dependências do projeto
  • change:
    • Uso: utilize esse tipo para quando for fazer alterações na implementação de um recurso existente. Isso ajuda a documentar de forma mais mais precisa as melhorias feitas em funcionalidades já existentes.
    • Exemplo: change: Melhorar a interface de usuário do painel de controle
  • chore:
    • Uso: commits desse tipo são ideais para tarefas de manutenção técnica ou preventiva que não estão diretamente relacionadas a recursos específicos ou histórias de usuário. Por exemplo, a liberação do produto pode ser considerada uma tarefa de manutenção.
    • Exemplo: chore: Preparar para a próxima versão de lançamento
  • ci:
    • Uso: quando você faz alterações nos scripts de integração contínua, entrega contínua ou arquivos de configuração, utilize esse tipo de commit para rastreá-las.
    • Exemplo: ci: Atualizar configurações do pipeline de CI/CD
  • deprecate:
    • Uso: esse tipo de commit é útil quando você deseja sinalizar que uma funcionalidade existente está sendo descontinuada, mas ainda não será removida do produto. É uma maneira de incentivar os desenvolvedores a migrar para alternativas mais recentes.
    • Exemplo: deprecate: Marcar API de notificação como obsoleta
  • docs:
    • Uso: utilize esse tipo quando você for fazer adições, atualizações ou revisões na documentação armazenada no repositório. Isso ajuda a manter a documentação do projeto sempre atualizada.
    • Exemplo: docs: Atualizar documentação do desenvolvedor
  • feat:
    • Uso: quando você implementar um novo recurso ou funcionalidade em seu aplicativo, use esse tipo para destacar a adição.
    • Exemplo: feat: Adicionar funcionalidade de pesquisa avançada
  • fix:
    • Uso: commits desse tipo são usados para indicar que um defeito ou problema foi corrigido no aplicativo.
    • Exemplo: fix: Corrigir erro de validação de formulário
  • perf:
    • Uso: utilize esse tipo quando for fazer melhorias no desempenho dos algoritmos ou no tempo geral de execução do produto, sem alterar fundamentalmente um recurso existente.
    • Exemplo: perf: Otimizar algoritmo de ordenação
  • refactor:
    • Uso: commits de refatoração indicam que o código existente foi reestruturado, mas o comportamento geral do produto permanece inalterado.
    • Exemplo: refactor: Refatorar módulo de autenticação
  • remove:
    • Uso: quando você precisar remover um recurso do produto, geralmente após marcá-lo como obsoleto por um período de tempo, utilize esse tipo.
    • Exemplo: remove: Remover suporte a versões antigas do protocolo
  • revert:
    • Uso: commits de reversão são usados para desfazer um ou mais commits anteriores, que foram incluídos acidentalmente ou causaram problemas sérios que exigiram sua remoção.
    • Exemplo: revert: Reverter mudanças que causaram falhas no servidor
  • security:
    • Uso: esse tipo é apropriado quando for fazer melhorias na segurança do produto ou resolver problemas de segurança relatados.
    • Exemplo: security: Corrigir vulnerabilidade de injeção de SQL
  • style:
    • Uso: utilize commits de estilo quando for fazer atualizações ou reformatações no estilo do código-fonte, sem alterar a implementação do produto.
    • Exemplo: style: Ajustar formatação do código
  • test:
    • Uso: commits de teste são usados para aprimorar, adicionar, revisar ou alterar o conjunto de testes automatizados do produto.
    • Exemplo: test: Adicionar testes unitários para módulo de autenticação

Caso tenha interesse em se aprofundar um pouco mais, recomendo a leitura do artigo “Conventional Commits: A Better Way, de Michael Collins.

Mapeando Tipos de Commit

Você pode mapear os tipos de commit para títulos de registro de alterações como uma prática útil, tornando mais fácil para as equipes e partes interessadas entenderem as mudanças feitas em cada versão do seu projeto.

feat → "Adicionado"

change → "Alterado"

deprecate → "Obsoleto"

remove → "Removido"

fix → "Corrigido"

security → "Segurança"

Vamos analisar alguns exemplos práticos para entender melhor como as mensagens de commit funcionam com o Conventional Commits:

Adicionando um novo recurso:

feat: adicionar funcionalidade de notificação por email

Agora, os usuários receberão notificações por email quando novos eventos ocorrerem.

Nesse exemplo, o tipo de commit feat indica que um novo recurso foi adicionado.

Corrigindo um problema:

fix: resolver erro de carregamento lento do aplicativo

A tela de carregamento agora aparece corretamente durante o processo de inicialização.

Aqui, o tipo de commit fix sinaliza que um problema foi corrigido.

Mudança que quebra a compatibilidade:

feat!: enviar notificações por email

BREAKING CHANGE: A partir de agora, as notificações por email não suportam versões anteriores.

Nesse caso, adicionamos um ! após o tipo de commit para destacar que esta é uma mudança significativa que quebra a compatibilidade.

Melhorando a configuração de compilação:

build: Atualizar sistema de compilação e dependências externas

Esta atualização inclui melhorias na configuração de compilação e atualização de dependências externas para manter o projeto atualizado.

Aqui, usamos o tipo de commit build para destacar as mudanças na infraestrutura de compilação do projeto.

Atualização de documentação:

docs: Atualizar guia do desenvolvedor

Esta atualização envolve adições e revisões na documentação do guia do desenvolvedor, tornando-a mais completa e informativa.

O tipo docs é perfeito para acompanhar mudanças na documentação do projeto.

Depreciação de recurso:

deprecate: Marcar API de notificação como obsoleta

Esta ação sinaliza que a API de notificação está obsoleta e incentiva os desenvolvedores a migrarem para alternativas mais recentes.

O tipo deprecate é usado quando uma funcionalidade está sendo descontinuada, mas ainda não foi removida.

Aprimoramento de testes:

test: Adicionar testes de unidade para módulo de geração de relatórios

Estes testes de unidade foram adicionados para melhorar a cobertura de código e a confiabilidade do módulo de geração de relatórios.

O tipo test é empregado quando aprimoramos o conjunto de testes automatizados do projeto.

Por que usar Conventional Commits?

Beleza, mas depois de aprender tudo isso sobre o Conventional Commits, você deve está se perguntando: Por que eu deveria implementar o Conventional Commits em meus projetos de desenvolvimento? Vou te dar quatro motivos para refletir:

  • Criação automatizada de CHANGELOGs: com mensagens de commit estruturadas, você pode automatizar a criação de CHANGELOGs, tornando mais fácil para todos acompanhar as mudanças em seu projeto;
  • Determinação automática do versionamento semântico: Com base nos tipos de commits, você pode automatizar a determinação de mudanças no versionamento semântico, economizando tempo e evitando erros humanos;
  • Comunicação clara e eficiente: mensagens de commit bem definidas facilitam a comunicação entre a equipe de desenvolvimento, partes interessadas e colaboradores externos;
  • Processos de build e deploy simplificados: integrar o Conventional Commits em seus processos de build e deploy é mais simples quando você tem mensagens de commit consistentes e estruturadas.

Conclusão

Nesse artigo, aprendemos que o Conventional Commits é uma especificação valiosa que simplifica o controle de versão e melhora a colaboração em projetos de desenvolvimento de software. Ao adotar essa especificação simples, você pode criar mensagens de commit claras e organizadas, facilitando a vida de todos os envolvidos no projeto. O nível de organização de seus projetos e o seu histórico de commits no repositório será melhor ainda.

E claro, se você quiser aprender mais sobre versionamento, controle de versões, como desenvolver e publicar uma biblioteca de componentes do zero, recomendo que você faça a formação Next.js e Tailwind: construindo um design system, que tá incrível!!

E então, já tinha ouvido falar sobre Conventional Commits? Já usou essa especificação em algum de seus projetos? Conta pra gente, marcando os perfis da Alura em suas redes sociais e usando a hastag #AprendiNaAlura para compartilhar sua experiência de desenvolvimento.

Até a próxima!

Neilton Seguins
Neilton Seguins

Sou graduado como Bacharel em Ciência e Tecnologia e em Engenharia Mecânica. Atuo como Instrutor de Desenvolvedor de Software na Alura e possuo experiência com desenvolvimento usando JavaScript/TypeScript, React js, Next js e Node.js. Amo compartilhar conhecimento, pois acredito que a educação é transformadora e quero mudar a vida de pessoas através da educação assim como consegui mudar de vida. Também amo ouvir e tocar música, ler livros e mangás e assistir séries.

Veja outros artigos sobre Front-end