DEV Community

Cover image for Conventional Commits: Guia Completo para Padronizar suas Mensagens de Commit
Luis Cruz
Luis Cruz

Posted on

Conventional Commits: Guia Completo para Padronizar suas Mensagens de Commit

Abra o histórico de commits de qualquer projeto que já passou por várias mãos e você vai encontrar de tudo: "fix", "ajustes", "correção final", "correção final 2", "wip". Nenhuma dessas mensagens diz o que mudou, por que mudou, ou se quebra algo. O resultado prático: gerar um changelog vira trabalho manual, descobrir quando um bug foi introduzido vira arqueologia, e decidir se a próxima versão é 1.2.0 ou 2.0.0 vira palpite.

É esse o problema que o Conventional Commits resolve: uma convenção leve para escrever mensagens de commit de um jeito que tanto humanos quanto máquinas conseguem interpretar, permitindo automatizar changelog, versionamento semântico e até gatilhos de CI a partir do próprio histórico do Git.

Este artigo cobre a origem da especificação, para que ela serve, sua estrutura formal e exemplos práticos do dia a dia.


Como e por que surgiu

O Conventional Commits nasceu da observação de que vários projetos open source já usavam, de forma independente, convenções parecidas para prefixar mensagens de commit. O Angular Commit Message Guidelines é a referência mais citada como origem direta do formato. A ideia central do Angular era simples: prefixar cada commit com um tipo (feat, fix, docs...) para que uma ferramenta pudesse gerar o CHANGELOG.md automaticamente, sem depender de alguém escrever isso manualmente a cada release.

A especificação Conventional Commits 1.0.0 consolidou essa prática em um padrão formal, documentado e versionado, inspirado também no SemVer, com o qual se integra diretamente (mais sobre isso adiante). Hoje é mantida como projeto aberto em conventionalcommits.org, com traduções para várias línguas, incluindo português.


Para que serve

Necessidade Como o Conventional Commits ajuda
Gerar changelog automaticamente Ferramentas leem o histórico e montam o CHANGELOG.md sem intervenção manual
Determinar a próxima versão semântica fix sugere PATCH, feat sugere MINOR, BREAKING CHANGE sugere MAJOR
Comunicar a natureza da mudança ao time Quem revisa o PR já sabe se é bug, feature ou refatoração antes de abrir o diff
Disparar builds e pipelines automaticamente CI pode decidir se publica um pacote, dispara um deploy ou pula uma etapa com base no tipo de commit
Facilitar contribuição em projetos abertos Reduz a barreira para quem nunca contribuiu entender como categorizar a própria mudança

Na prática, o ganho não é estético, é que o histórico do Git passa a ser dado estruturado, não só texto livre, e dá para automatizar em cima dele.


Estrutura da mensagem

O formato básico definido pela especificação é:

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

[corpo opcional]

[rodapé(s) opcional(is)]
Enter fullscreen mode Exit fullscreen mode

Os tipos mais usados

Tipo Quando usar
feat Nova funcionalidade (correlaciona com MINOR no SemVer)
fix Correção de bug (correlaciona com PATCH no SemVer)
docs Mudança apenas em documentação
style Formatação, espaços, ponto e vírgula, sem mudança de lógica
refactor Mudança de código que não corrige bug nem adiciona feature
perf Mudança que melhora performance
test Adição ou correção de testes
build Mudança no sistema de build ou dependências externas
ci Mudança em arquivos e scripts de CI/CD
chore Tarefas de manutenção que não afetam código de produção

A especificação define oficialmente apenas feat e fix como obrigatórios para a relação com SemVer. Os demais tipos (baseados na convenção do Angular) são uma extensão amplamente adotada, mas o time pode ajustar a lista conforme a necessidade do projeto.


Exemplos práticos

Commit simples

feat: adiciona endpoint de exportação de relatórios em PDF
Enter fullscreen mode Exit fullscreen mode

Commit com escopo

O escopo (entre parênteses) indica qual parte do código foi afetada:

fix(auth): corrige expiração prematura do token JWT
Enter fullscreen mode Exit fullscreen mode
feat(checkout): adiciona suporte a pagamento via Pix
Enter fullscreen mode Exit fullscreen mode

Commit com corpo explicando o contexto

fix(api): corrige timeout em requisições de upload grandes

O timeout estava fixo em 30s independente do tamanho do arquivo.
Agora o timeout escala proporcionalmente ao tamanho do payload,
com um teto máximo de 5 minutos.
Enter fullscreen mode Exit fullscreen mode

Commit com breaking change

Uma mudança que quebra compatibilidade é sinalizada com ! após o tipo/escopo, ou com o rodapé BREAKING CHANGE: os dois podem ser usados juntos:

feat(api)!: remove suporte ao endpoint /v1/users

BREAKING CHANGE: o endpoint /v1/users foi descontinuado.
Use /v2/users, que retorna o campo `email` como obrigatório.
Enter fullscreen mode Exit fullscreen mode

Esse commit, por conter BREAKING CHANGE, indica que a próxima versão deve ser um MAJOR no versionamento semântico (ex: 2.4.13.0.0), independente de conter também um feat.

Commit apenas de manutenção

chore: atualiza dependências de dev para as versões mais recentes
Enter fullscreen mode Exit fullscreen mode

Múltiplos rodapés

Rodapés seguem o mesmo formato de trailers do Git (chave: valor), e podem referenciar issues, coautores ou revisores:

fix(payments): corrige arredondamento incorreto no cálculo de juros

Refs: #482
Reviewed-by: Ana Costa
Co-authored-by: João Silva <joao@example.com>
Enter fullscreen mode Exit fullscreen mode

Relação com Versionamento Semântico (SemVer)

A especificação foi desenhada para mapear diretamente para as três posições do SemVer (MAJOR.MINOR.PATCH):

Tipo de commit Impacto na versão Exemplo
fix PATCH 1.4.21.4.3
feat MINOR 1.4.21.5.0
Qualquer tipo com BREAKING CHANGE ou ! MAJOR 1.4.22.0.0
docs, style, chore, test, etc. Nenhum (não gera release)

Essa correlação é o que permite que ferramentas de release automatizem a decisão de qual versão publicar, sem que ninguém precise decidir manualmente "isso é uma minor ou uma patch?".


Ferramentas do ecossistema

Ferramenta Função
commitlint Valida no commit (via hook) se a mensagem segue o padrão
commitizen CLI interativa que monta a mensagem de commit por perguntas
semantic-release Automatiza versionamento e publicação de pacotes com base nos commits
standard-version Gera changelog e bump de versão localmente, sem publicar
conventional-changelog Biblioteca base para gerar changelogs a partir do histórico

Exemplo de hook local com commitlint

npm install --save-dev @commitlint/cli @commitlint/config-conventional
Enter fullscreen mode Exit fullscreen mode
// commitlint.config.js
module.exports = { extends: ['@commitlint/config-conventional'] };
Enter fullscreen mode Exit fullscreen mode

Integrando com Husky para rodar a validação em todo commit:

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'
Enter fullscreen mode Exit fullscreen mode

A partir daí, um commit fora do padrão é rejeitado antes mesmo de entrar no histórico:

$ git commit -m "ajustei umas coisas"
⧗   input: ajustei umas coisas
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

✖ found 2 problems, 0 warnings
Enter fullscreen mode Exit fullscreen mode

Boas práticas

  • Descrição no imperativo, minúscula, sem ponto final — ex: fix: corrige, não fix: Corrigido. ou fix: correção de
  • Um commit, uma mudança lógica — evite misturar feat e refactor no mesmo commit só porque tocaram os mesmos arquivos
  • Escopo consistente — combine com o time uma lista fixa de escopos (auth, api, ui, db) em vez de deixar livre
  • Corpo explica o "porquê", não o "o quê" — o diff já mostra o que mudou; o corpo do commit deve justificar a decisão
  • BREAKING CHANGE sempre no rodapé, em maiúsculas — é o texto que as ferramentas de automação procuram para disparar um MAJOR
  • Combine com commitlint no pipeline ou pre-commit hook — depender de disciplina manual do time não escala além de poucas pessoas

Troubleshooting

Problema Causa provável Solução
commitlint rejeita commit com mensagem que parece correta Espaço faltando após os dois-pontos, ou tipo com maiúscula (Feat:) Sempre tipo: descrição, tipo em minúsculas, um espaço após :
Changelog gerado não lista uma mudança importante Commit usou tipo que não gera changelog por padrão (chore, style) Reclassifique como feat/fix se a mudança for relevante ao usuário final
semantic-release não bumpou a versão MAJOR esperada BREAKING CHANGE escrito errado no corpo (ex: Breaking change: com minúscula) Use exatamente BREAKING CHANGE: maiúsculo, ou ! após o tipo/escopo
Time reclama que o padrão é burocrático demais Falta de ferramenta que automatize a checagem, virando esforço manual Adicione commitizen para gerar a mensagem por prompt interativo, reduzindo fricção
Merge commit "genérico" polui o changelog Merge de branch sem squash mistura vários commits não convencionais Prefira squash merge com uma mensagem convencional única no PR

Conclusão

Conventional Commits não é sobre burocratizar o Git, é sobre transformar uma mensagem de commit em um dado que máquinas conseguem ler, sem tirar a legibilidade para humanos. O ganho aparece principalmente na escala: um projeto pequeno sobrevive com "fix bug", mas um projeto com múltiplos contribuidores, releases frequentes e changelog público sente a diferença entre montar isso manualmente ou automaticamente a cada versão.

Comece pequeno: adote feat: e fix: no seu próximo commit, adicione o commitlint como hook local, e deixe o time se acostumar antes de cobrar escopos e rodapés. Depois de validado no dia a dia, avalie ferramentas como semantic-release para automatizar versionamento e publicação por completo.


Referências

Top comments (1)

Collapse
 
topstar_ai profile image
Luis

Great guide. Conventional Commits may seem like a small practice, but they create a strong foundation for better collaboration, automation, and maintainability. Clear commit messages make it easier to understand project history, generate changelogs, and integrate with CI/CD workflows.

The biggest value is not the exact format — it’s creating a shared language across the team. When everyone follows a consistent convention, reviewing changes and tracing decisions becomes much easier.

Simple engineering habits like this often have a compounding effect as projects and teams grow. Great resource for developers looking to improve their workflow!