Changelog generation: criando CHANGELOG.md a partir de commits
1. Introdução à Geração Automática de Changelogs
Manter um changelog manual é uma tarefa ingrata. Em projetos com múltiplos contribuidores, o arquivo CHANGELOG.md frequentemente fica desatualizado, com entradas genéricas ou simplesmente inexistente. Automatizar sua geração a partir dos commits resolve esse problema, garantindo que cada release tenha um registro preciso e detalhado das mudanças.
Os benefícios são claros: economia de tempo, consistência entre releases, rastreabilidade total das alterações e documentação viva que evolui com o código. A diferença entre um changelog manual e um gerado por commits é a diferença entre um resumo subjetivo e um relatório objetivo baseado em dados.
O pré-requisito fundamental para essa automação funcionar é ter commits bem escritos, seguindo uma convenção padronizada. Sem isso, seu changelog será tão caótico quanto suas mensagens de commit.
2. Estrutura e Padrões de Commits para Changelogs Eficazes
A espinha dorsal de qualquer geração automatizada de changelog é a Convenção de Commits Semânticos (Conventional Commits). Esse padrão define uma estrutura clara para mensagens de commit:
<tipo>(<escopo opcional>): <descrição>
<corpo opcional>
<rodapé opcional>
Os tipos mais comuns mapeiam diretamente para seções do changelog:
feat:— Nova funcionalidade (entra em "Novas funcionalidades")fix:— Correção de bug (entra em "Correções")BREAKING CHANGE:— Mudança que quebra compatibilidade (entra em "Breaking Changes")docs:— Documentação (geralmente omitida ou em seção separada)refactor:— Refatoração (não aparece no changelog por padrão)chore:— Tarefas de manutenção (ignorada)
Exemplo prático de commits bem formatados:
feat(api): adicionar endpoint de autenticação JWT
fix(ui): corrigir layout quebrado no Safari
BREAKING CHANGE: alterar formato de resposta da API de XML para JSON
docs: atualizar README com instruções de instalação
3. Ferramentas Nativas do Git para Extração de Commits
O Git oferece comandos poderosos para extrair e formatar commits. O git log é sua principal ferramenta:
git log --oneline --format="%s" v1.0.0..v2.0.0
Esse comando lista todos os commits entre duas tags. Para agrupar por tipo:
git log v1.0.0..v2.0.0 --grep="^feat" --format="- %s"
git log v1.0.0..v2.0.0 --grep="^fix" --format="- %s"
O git shortlog cria um resumo agrupado por autor:
git shortlog v1.0.0..v2.0.0 -sn
Para filtrar por data (útil quando não há tags):
git log --since="2024-01-01" --until="2024-03-31" --format="%s"
4. Scripts e Automação Manual com Shell
Você pode criar um script Bash simples para gerar um changelog básico. Aqui está um exemplo funcional:
#!/bin/bash
# changelog-generator.sh
# Uso: ./changelog-generator.sh v1.0.0 v2.0.0
FROM_TAG=$1
TO_TAG=$2
echo "# Changelog"
echo ""
echo "## [$TO_TAG] - $(date +%Y-%m-%d)"
echo ""
echo "### Novas funcionalidades"
echo ""
git log $FROM_TAG..$TO_TAG --grep="^feat" --format="- %s (%h)" | sed 's/^feat: //'
echo ""
echo "### Correções"
echo ""
git log $FROM_TAG..$TO_TAG --grep="^fix" --format="- %s (%h)" | sed 's/^fix: //'
echo ""
echo "### Breaking Changes"
echo ""
git log $FROM_TAG..$TO_TAG --grep="BREAKING CHANGE" --format="- %s (%h)"
echo ""
Execute com:
chmod +x changelog-generator.sh
./changelog-generator.sh v1.0.0 v2.0.0 > CHANGELOG.md
Para projetos sem tags, use --since:
git log --since="2024-01-01" --until="2024-06-01" --format="%s" > changelog_raw.txt
5. Ferramentas Populares de Terceiros
git-cliff
Ferramenta altamente configurável que usa templates Tera:
# Instalação
cargo install git-cliff
# Configuração básica
git cliff --init
# Geração
git cliff -o CHANGELOG.md
standard-version
Integrado com versionamento semântico:
npm install -g standard-version
standard-version --release-as minor
auto-changelog
Simples e direto, baseado em tags:
npm install -g auto-changelog
auto-changelog -p
6. Customização e Templates Avançados
Com git-cliff, você pode criar templates complexos. Exemplo de configuração cliff.toml:
[changelog]
header = "# Changelog\n\n"
body = """
{% if version %}\n## [{{ version }}] - {{ timestamp | date(format="%Y-%m-%d") }}{% endif %}\n
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message }}{% if commit.author %} ({{ commit.author }}){% endif %}
{% endfor %}
{% endfor %}
"""
Para incluir links para issues e PRs, use expressões regulares no commit:
git log --format="- %s (fixes #%b)" | grep -E "#[0-9]+"
7. Integração com CI/CD e Fluxo de Trabalho
GitHub Actions
Crie um workflow .github/workflows/release.yml:
name: Generate Changelog
on:
push:
tags:
- 'v*'
jobs:
changelog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
run: |
git cliff --unreleased --strip all > CHANGELOG.md
git add CHANGELOG.md
git commit -m "docs: update changelog for ${{ github.ref_name }}"
git push
GitLab CI
stages:
- changelog
generate-changelog:
stage: changelog
script:
- git cliff -o CHANGELOG.md
- git add CHANGELOG.md
- git commit -m "docs: update changelog"
- git push origin HEAD:$CI_COMMIT_BRANCH
only:
- tags
Para validação de commits, use commitlint:
npm install -g @commitlint/cli @commitlint/config-conventional
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
8. Manutenção e Boas Práticas Contínuas
Nem todos os commits serão perfeitamente categorizados. Para lidar com commits não formatados:
# Capturar commits que não seguem o padrão
git log --format="%s" | grep -vE "^(feat|fix|docs|chore|refactor|BREAKING CHANGE)"
Estratégias para múltiplos contribuidores:
- Defina uma política clara no CONTRIBUTING.md
- Implemente hooks de validação com
huskyecommitlint - Use squash merges para limpar o histórico antes de releases
- Revise manualmente o changelog gerado antes de publicar
O versionamento do próprio CHANGELOG.md é controverso. A recomendação é:
- Nunca editar manualmente o arquivo gerado automaticamente
- Adicionar entradas manuais apenas em seção separada ("Notas da release")
- Versionar o template e a configuração, não o arquivo final
Se precisar de edição manual, crie um arquivo CHANGELOG_MANUAL.md que será mesclado ao gerado automaticamente.
Referências
- Conventional Commits 1.0.0 — Especificação oficial do padrão de mensagens de commit que fundamenta a geração automatizada de changelogs
- git-cliff Documentation — Documentação oficial da ferramenta de geração de changelogs altamente configurável com templates Tera
- Keep a Changelog — Padrão recomendado para estrutura de arquivos CHANGELOG.md, com boas práticas de organização
- standard-version GitHub Repository — Ferramenta de versionamento semântico que gera changelogs automaticamente a partir de commits convencionais
- Git Log Documentation — Documentação oficial do Git sobre o comando
git log, essencial para extração e formatação de commits - commitlint GitHub Repository — Ferramenta de validação de mensagens de commit baseada em regras configuráveis
- semantic-release GitHub Repository — Sistema automatizado de versionamento e publicação que inclui geração de changelog