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.
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.
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 oufix
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 chamadaBREAKING 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!