Commits Convencionais
Componha mensagens de commit seguindo a especificação Conventional Commits v1.0.0 para um histórico estruturado, geração automatizada de changelogs e versionamento semântico.
Quando Usar Esta Skill
Use esta skill quando:
- Criando mensagens de commit git para projetos estruturados
- Validando o formato de mensagens de commit contra a especificação Conventional Commits
- Configurando validação de mensagens de commit com commitlint
- Configurando geração de changelogs a partir do histórico de commits
- Implementando automação de versionamento semântico
- Revisando mensagens de commit quanto à conformidade com a especificação
- Treinando equipes nos padrões de mensagens de commit
- Integrando com ferramentas como semantic-release, commitizen ou git-cliff
Estrutura da Mensagem
<tipo>[escopo opcional]: <descrição>
[corpo opcional]
[rodapé(s) opcional(is)]
Componentes
| Componente | Obrigatório | Descrição | Exemplo |
|---|---|---|---|
| tipo | Sim | Categoria do commit | feat, fix, docs |
| escopo | Não | Seção do código afetada | (auth), (parser) |
| descrição | Sim | Resumo curto das mudanças | adicionar autenticação de usuário |
| corpo | Não | Explicação detalhada | Múltiplos parágrafos com contexto |
| rodapé | Não | Mudanças de quebra, refs de issues | BREAKING CHANGE:, Refs: #123 |
Tipos de Commit
Tipos Obrigatórios (Impacto SemVer)
Estes tipos são exigidos pela especificação Conventional Commits e afetam diretamente o versionamento semântico:
flowchart LR
Fix[fix: Correção de bug<br/>para usuários] --> PatchVer[PATCH<br/>0.0.X]
Feat[feat: Nova funcionalidade<br/>para usuários] --> MinorVer[MINOR<br/>0.X.0]
Breaking[Qualquer tipo com<br/>BREAKING CHANGE ou !] --> MajorVer[MAJOR<br/>X.0.0]
style PatchVer fill:#e1f5ff
style MinorVer fill:#fff4e1
style MajorVer fill:#ffe1e1
| Tipo | Descrição | SemVer | Exemplo |
|---|---|---|---|
feat | Nova funcionalidade para usuários | MINOR (0.X.0) | feat: adicionar autenticação de usuário |
fix | Correção de bug para usuários | PATCH (0.0.X) | fix: evitar crash em entrada vazia |
Tipos Recomendados (Convenção Angular)
Estes tipos vêm do @commitlint/config-conventional baseado nas diretrizes de commit do Angular. Eles não têm efeito SemVer implícito, a menos que incluam BREAKING CHANGE.
| Tipo | Descrição | Exemplo |
|---|---|---|
build | Mudanças no sistema de build ou dependências externas | build: atualizar webpack para v5 |
ci | Mudanças na configuração de CI | ci: adicionar Node 18 à matriz de teste |
docs | Mudanças apenas na documentação | docs: atualizar referência da API |
perf | Melhoria de performance | perf: reduzir tamanho do bundle em 20% |
refactor | Mudança no código sem correção de bug ou funcionalidade | refactor: extrair lógica de validação |
style | Mudanças de estilo de código (espaçamento, formatação) | style: corrigir indentação |
test | Adição ou correção de testes | test: adicionar testes unitários para o parser |
Tipos Comuns Adicionais
| Tipo | Descrição | Exemplo |
|---|---|---|
chore | Mudanças que não modificam arquivos src ou test | chore: atualizar .gitignore |
revert | Reverte um commit anterior | revert: feat: adicionar auth de usuário |
Nota: Equipes podem definir tipos personalizados além de feat e fix, mas os tipos da convenção Angular são amplamente suportados por ferramentas.
Regras da Especificação
As regras a seguir constituem a especificação oficial Conventional Commits 1.0.0 conforme RFC 2119.
Tipo e Escopo
-
Commits DEVEM ser prefixados com um tipo, consistindo em um substantivo (
feat,fix, etc.), seguido por escopo OPCIONAL,!OPCIONAL, e dois pontos e espaço OBRIGATÓRIOS no final. -
O tipo
featDEVE ser usado quando um commit adiciona uma nova funcionalidade. -
O tipo
fixDEVE ser usado quando um commit representa uma correção de bug. -
Um escopo PODE ser fornecido após o tipo. Um escopo DEVE consistir em um substantivo descrevendo uma seção do código entre parênteses, por exemplo,
fix(parser): -
Uma descrição DEVE seguir imediatamente os dois pontos e o espaço após o prefixo tipo/escopo. A descrição é um resumo curto das mudanças, por exemplo,
fix: problema de análise de array quando múltiplos espaços estavam contidos na string
Corpo
-
Um corpo de commit mais longo PODE ser fornecido após a descrição curta, fornecendo informações contextuais adicionais. O corpo DEVE começar uma linha em branco após a descrição.
-
Um corpo de commit é de forma livre e PODE consistir em qualquer número de parágrafos separados por nova linha.
Rodapé
-
Um ou mais rodapés PODEM ser fornecidos uma linha em branco após o corpo. Cada rodapé DEVE consistir em um token de palavra, seguido por um separador
:<space>ou<space>#, seguido por um valor string (inspirado na convenção git trailer). -
O token de um rodapé DEVE usar
-no lugar de caracteres de espaço em branco, por exemplo,Acked-by(isso ajuda a diferenciar a seção de rodapé do corpo de múltiplos parágrafos). Exceção:BREAKING CHANGEPODE também ser usado como token. -
O valor de um rodapé PODE conter espaços e novas linhas. A análise DEVE terminar quando o próximo par token/separador de rodapé válido for observado.
Mudanças de Quebra
-
Mudanças de quebra DEVEM ser indicadas no prefixo tipo/escopo de um commit, ou como uma entrada no rodapé.
-
Se incluída como rodapé, uma mudança de quebra DEVE consistir no texto em maiúsculas
BREAKING CHANGE, seguido por dois pontos, espaço e descrição, por exemplo,BREAKING CHANGE: variáveis de ambiente agora têm precedência sobre arquivos de configuração -
Se incluída no prefixo tipo/escopo, mudanças de quebra DEVEM ser indicadas por
!imediatamente antes de:. Se!for usado,BREAKING CHANGE:PODE ser omitido do rodapé, e a descrição do commit DEVERÁ ser usada para descrever a mudança de quebra.
Regras Adicionais
-
Tipos diferentes de
featefixPODEM ser usados em mensagens de commit, por exemplo,docs: atualizar docs de referência -
As unidades de informação que compõem Conventional Commits NÃO DEVEM ser tratadas como sensíveis a maiúsculas/minúsculas pelos implementadores, exceto
BREAKING CHANGEque DEVE estar em maiúsculas. -
BREAKING-CHANGEDEVE ser sinônimo deBREAKING CHANGEquando usado como token em um rodapé.
Boas Práticas de Descrição
Baseado nas diretrizes de mensagens de commit do Angular:
Diretrizes de Resumo/Descrição
- Use imperativo, tempo presente: "altera" em vez de "alterou" ou "alterações"
- Não capitalize a primeira letra
- Sem ponto (.) no final
- Mantenha todo o cabeçalho (tipo + escopo + descrição) abaixo de 72 caracteres
Exemplos Bons
feat: adicionar validação para entrada de email
fix: tratar ponteiro nulo no serviço de usuário
docs: atualizar instruções de instalação
refactor: simplificar fluxo de autenticação
Exemplos Ruins (Evitar)
feat: Adicionada validação para entrada de email # Tempo passado
fix: Trata ponteiro nulo no serviço de usuário # Terceira pessoa
docs: Atualizar instruções de instalação. # Ponto no final, capitalizado
FEAT: adicionar validação # Tipo maiúsculo (inconsistente)
Diretrizes do Corpo
- Use imperativo, tempo presente (mesmo que o resumo)
- Explique a motivação para a mudança
- Inclua comparação do comportamento anterior vs novo quando útil
- Corpo DEVE começar com uma linha em branco após a descrição
- Mínimo recomendado: 20 caracteres quando o corpo está presente
Mudanças de Quebra
Métodos para Indicar Mudanças de Quebra
Três abordagens equivalentes:
-
Notação de rodapé:
feat: permitir que objeto de configuração fornecido estenda outras configurações BREAKING CHANGE: a chave `extends` no arquivo de configuração agora é usada para estender outros arquivos de configuração -
Sufixo de tipo com
!:feat!: remover suporte para Node 6 -
Sufixo de tipo+escopo com
!:feat(api)!: enviar um email ao cliente quando um produto é enviado
Regras
BREAKING CHANGEDEVE estar em maiúsculasBREAKING-CHANGEé sinônimo quando usado como token de rodapé- Mudanças de quebra DEVEM correlacionar-se com um incremento MAJOR no SemVer
Correlação com Versionamento Semântico
flowchart TD
Start([Analisar Commits]) --> CheckBreaking{Algum commit tem<br/>BREAKING CHANGE<br/>ou !?}
CheckBreaking -->|Sim| Major[Incremento MAJOR<br/>X.0.0]
CheckBreaking -->|Não| CheckFeat{Algum commit<br/>é feat?}
CheckFeat -->|Sim| Minor[Incremento MINOR<br/>0.X.0]
CheckFeat -->|Não| CheckFix{Algum commit<br/>é fix?}
CheckFix -->|Sim| Patch[Incremento PATCH<br/>0.0.X]
CheckFix -->|Não| NoChange[Nenhuma mudança de versão]
Major --> End([Lançamento])
Minor --> End
Patch --> End
NoChange --> End
Mapeamento de Tipo de Commit para Versão
| Tipo de Commit | Incremento de Versão |
|---|---|
fix | PATCH (0.0.X) |
feat | MINOR (0.X.0) |
BREAKING CHANGE ou ! | MAJOR (X.0.0) |
Razão: Permite versionamento semântico automatizado baseado no histórico de commits.
Padrões de Validação
Regex de Validação do Cabeçalho
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?:\s.+$
Exemplo de Validação em Python
import re
CONVENTIONAL_COMMIT_PATTERN = re.compile(
r"^(?P<type>feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)"
r"(?:\((?P<scope>[^)]+)\))?"
r"(?P<breaking>!)?"
r":\s"
r"(?P<description>.+)$"
)
def validate_header(header: str) -> bool:
"""Validar se o cabeçalho do commit segue Commits Convencionais."""
return bool(CONVENTIONAL_COMMIT_PATTERN.match(header))
def parse_header(header: str) -> dict | None:
"""Analisar cabeçalho do commit em componentes."""
match = CONVENTIONAL_COMMIT_PATTERN.match(header)
if not match:
return None
return {
"type": match.group("type"),
"scope": match.group("scope"),
"breaking": bool(match.group("breaking")),
"description": match.group("description"),
}
Exemplos Completos
Commits Simples
feat: adicionar autenticação de usuário
fix: evitar crash em entrada vazia
docs: corrigir ortografia de CHANGELOG
Commits com Escopo
feat(lang): adicionar idioma polonês
feat(parser): adicionar capacidade de analisar arrays
fix(auth): tratar expiração de token corretamente
Mudanças de Quebra
feat: permitir que objeto de configuração fornecido estenda outras configurações
BREAKING CHANGE: a chave `extends` no arquivo de configuração agora é usada para estender outros arquivos de configuração
feat!: enviar um email ao cliente quando um produto é enviado
feat(api)!: enviar um email ao cliente quando um produto é enviado
chore!: remover suporte para Node 6
BREAKING CHANGE: usar funcionalidades JavaScript não disponíveis no Node 6
Corpo com Múltiplos Parágrafos e Rodapés
fix: evitar corrida de requisições
Introduzir um id de requisição e uma referência à requisição mais recente. Descartar
respostas recebidas que não sejam da requisição mais recente.
Remover timeouts que eram usados para mitigar o problema de corrida, mas estão
obsoletos agora.
Reviewed-by: Z
Refs: #123
Commit de Reversão
revert: nunca mais falemos do incidente do macarrão
Refs: 676104e, a215868
Melhoria de Performance
perf: reduzir alocação de memória no parser em 40%
Substituir concatenação de strings pelo padrão StringBuilder.
Resultados de benchmark mostram redução de 40% nas alocações de heap.
Refs: #456
Refatoração
refactor: extrair lógica de autenticação para módulo separado
Mover funções relacionadas a auth de utils.py para auth.py.
Sem mudanças funcionais.
Mudanças de Build/CI
ci: adicionar Node 18 à matriz de teste
build: atualizar webpack de v4 para v5
- Atualizar webpack.config.js para compatibilidade com v5
- Substituir plugins obsoletos
- Atualizar todas as dependências de loader
Refs: #789
Mudanças de Teste e Estilo
test: adicionar testes unitários para validação de usuário
Cobrir casos de borda para validação de email e força de senha.
style: formatar código de acordo com a configuração do prettier
chore: atualizar .gitignore para excluir arquivos de IDE
Integração com Ferramentas de Validação
Configuração do commitlint
Valide commits com commitlint usando a configuração Angular:
# Instalar commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Criar configuração
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
# Testar mensagem de commit
echo 'feat(api): adicionar novo endpoint' | npx commitlint
Para uma orientação abrangente sobre a configuração do commitlint, use as diretrizes neste documento. Se seu workspace tiver um plugin commitlint instalado, você pode delegar a ele as regras e exemplos específicos do projeto.
Hooks de Pré-commit
Force o formato da mensagem de commit com hooks de pré-commit. Se seu workspace tiver um plugin de pré-commit instalado, você pode usá-lo para orientação sobre configuração de hooks; caso contrário, configure os hooks diretamente.
Geração de Changelog
Gere changelogs a partir de Commits Convencionais usando semantic-release:
// release.config.js
module.exports = {
branches: ['main'],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/changelog',
['@semantic-release/npm', { npmPublish: false }],
['@semantic-release/git', {
assets: ['package.json', 'CHANGELOG.md'],
message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}'
}]
]
}
Ferramentas Complementares
- commitizen: Ferramenta CLI para ajudar a escrever Commits Convencionais
- git-cliff: Gerador de changelog altamente personalizável
- standard-version: Utilitário de versionamento e changelog via npm