CHANGELOG.md: o que vai nele e como mantê-lo atualizado
6 min de leitura
Um CHANGELOG.md é um arquivo Markdown na raiz de um repositório que lista, para cada versão lançada, o que mudou em termos sobre os quais um usuário do projeto consegue agir. O arquivo é lido por quem decide se atualiza, por quem depura depois de atualizar e por registros de pacotes e ferramentas de release que o renderizam na página do projeto. O formato que a maioria dos projetos segue é o descrito em keepachangelog.com: a versão mais nova no topo, uma seção Unreleased acima dela, e entradas agrupadas em Added, Changed, Deprecated, Removed, Fixed e Security.
| Seção | O que vai nela | Linha de exemplo |
|---|---|---|
Unreleased | Mudanças integradas mas ainda sem versão | - A exportação agora faz streaming, então arquivos acima de 100 MB não estouram mais o tempo limite. |
Added | Capacidade nova que um usuário alcança | - A flag \—dry-run` em `deploy` imprime o plano sem aplicá-lo.` |
Changed | Comportamento existente que agora funciona diferente | - Tempo limite padrão subiu de 30 s para 60 s. |
Deprecated | Ainda funciona, com remoção agendada | - \legacyAuth()` será removido na 3.0; use `auth()`.` |
Removed | Saiu nesta versão | - Suporte ao Node 16 descontinuado. |
Fixed | Um bug que um usuário pode ter encontrado | - A busca não falha mais em consultas com hífen. |
Security | Correções pelas quais o leitor deve atualizar hoje | - Corrigido um path traversal no handler de arquivos estáticos (CVE pendente). |
O que é um arquivo CHANGELOG.md?
É o histórico legível por humanos de um projeto, uma versão de cada vez, guardado ao lado do código para viajar com ele. Ele difere do git log em público e em seleção: o git log registra todo commit para as pessoas que o escreveram, enquanto o changelog registra as mudanças que um usuário notaria, escritas para a pessoa que não as escreveu. Um commit que renomeia uma variável interna não tem linha no changelog. Um commit que muda um tempo limite padrão tem, mesmo que o diff tenha sido um único caractere.
O arquivo mora na raiz do repositório, com exatamente esse nome, porque é lá que as ferramentas o procuram. O GitHub o linka na página do repositório, o npm e o PyPI o renderizam quando ele vai no pacote, e ferramentas de release como release-please e semantic-release o leem e escrevem no lugar. changelog.md em minúsculas e CHANGES.md também funcionam para pessoas, mas algumas ferramentas só procuram o nome canônico.
Como é um CHANGELOG.md completo?
Um exemplo curto e correto vale mais que uma descrição longa. Este segue o layout do Keep a Changelog 1.1.0 e o versionamento semântico para os números.
# Changelog
Todas as mudanças notáveis deste projeto estão listadas aqui.
Formato: Keep a Changelog. Versões: Versionamento Semântico.
## [Unreleased]
### Added
- A flag `--dry-run` em `deploy` imprime o plano sem aplicá-lo.
## [2.3.1] - 2026-10-01
### Fixed
- A busca não falha mais em consultas com hífen. Quebrada
desde a 2.3.0.
### Security
- Corrigido um path traversal no handler de arquivos estáticos.
Atualize hoje se você serve arquivos enviados por usuários.
## [2.3.0] - 2026-09-18
### Added
- Exportação com streaming. Arquivos acima de 100 MB não
estouram mais o tempo limite.
### Deprecated
- `legacyAuth()` ainda funciona, mas será removido na 3.0.
Use `auth()`.
[Unreleased]: https://github.com/acme/tool/compare/v2.3.1...HEAD
[2.3.1]: https://github.com/acme/tool/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/acme/tool/compare/v2.2.0...v2.3.0
Quatro detalhes carregam a maior parte do valor. Toda versão tem uma data em formato ISO, para o leitor cruzar com o momento em que o problema dele começou. Cada título de versão é um link para a visão de comparação, então o diff completo está a um clique. Uma correção diz qual versão quebrou aquilo. E a seção Security fica separada, para quem procura “preciso atualizar agora?” encontrá-la em segundos.
Como manter um CHANGELOG.md atualizado?
Escreva a linha no mesmo pull request da mudança, sob Unreleased, e mova a seção para um título de versão quando lançar. Esse é o método inteiro. O arquivo fica desatualizado quando a linha é escrita depois, por outra pessoa, na hora da release, a partir de uma lista de mensagens de commit que ela não escreveu.
Duas coisas fazem o hábito pegar. A primeira é uma verificação no CI que reprova um pull request que toca src/ sem tocar o changelog, com uma label para pular em mudanças sem efeito visível ao usuário; uma verificação de changelog como GitHub Action mostra a versão de quarenta linhas. A segunda é um passo de release que renomeia Unreleased para a versão e a data em um comando, para ninguém precisar lembrar de fazer isso à mão. Quem escreve o changelog cobre como as equipes resolvem a pergunta de quem é o dono da linha.
O changelog deve ser gerado a partir dos commits?
A geração dá a vocês um rascunho completo; ela não dá um changelog. Ferramentas construídas sobre conventional commits, e automações de release como o release-please, leem os prefixos feat:, fix: e BREAKING CHANGE: e produzem uma lista agrupada com todo pull request linkado. A lista é tão boa quanto os assuntos dos commits, e assuntos de commit descrevem o código.
O meio-termo que funciona é gerar e depois editar. Deixe a ferramenta criar a seção Unreleased a partir dos commits, e faça o pull request de release reescrever as linhas que um usuário leria: o sintoma em vez do nome da função, a configuração que mudou de lugar em vez do arquivo que mudou. De conventional commits a um changelog percorre o pipeline, e um gerador de changelog no navegador basta para tirar um rascunho de um git log colado sem instalar nada.
O que não deve ir no CHANGELOG.md?
Refatorações internas, atualizações de dependência sem mudança de comportamento, commits só de teste, configuração de CI e mudanças de formatação. Elas pertencem ao histórico do git, onde quem precisar as encontra. Incluí-las enterra as linhas que importam e ensina os leitores a pular o arquivo.
A outra coisa a deixar de fora é a versão de marketing de uma mudança. “Exportações ultrarrápidas” não diz ao leitor nada que ele consiga conferir. “A exportação agora faz streaming; arquivos acima de 100 MB não estouram mais o tempo limite” diz. O arquivo é um documento de referência, e o tom deve combinar: linhas curtas, substantivos concretos, uma versão ou data em tudo. Keep a Changelog, implementado cobre as partes da especificação que as equipes mais deixam cair, e formatos de arquivo de changelog cobre quando uma fonte JSON ou YAML ao lado do arquivo Markdown vale o custo.
Um produto com página de changelog ainda precisa do arquivo?
Uma biblioteca precisa, porque o arquivo é o que os registros de pacotes renderizam e o que um desenvolvedor lê offline. Um produto SaaS sem artefato instalável consegue viver só com a página, já que seus usuários nunca veem o repositório. Muitas equipes mantêm os dois: o arquivo como registro de engenharia, e uma página de changelog pública escrita a partir dele para um público mais amplo, com o detalhe dividido como changelog vs release notes descreve. Se a página é alimentada pelo arquivo, mantenha o arquivo como fonte de verdade e gere a página, para haver um só lugar para editar.
FAQ
Qual é a diferença entre CHANGELOG.md e release notes? O changelog é o registro completo e contínuo de toda mudança notável, guardado no repositório. Release notes são uma mensagem sobre uma release, geralmente mais curta e reescrita para um público mais amplo. Muitos projetos publicam a seção do changelog de uma versão como suas release notes.
Onde o CHANGELOG.md deve ficar? Na raiz do repositório, com exatamente esse nome, para o GitHub, os registros de pacotes e as ferramentas de release o encontrarem. Um monorepo mantém um por pacote, ao lado do manifesto de cada pacote.
Devo gerar o CHANGELOG.md a partir dos commits do git? Gere o rascunho e depois edite as linhas que um usuário vai ler. Mensagens de commit descrevem a mudança no código; o changelog descreve o que um usuário nota. Ferramentas como conventional-changelog e release-please dão um bom ponto de partida.
Todo commit precisa de uma entrada no changelog? Não. Só mudanças que um usuário do projeto poderia notar: capacidade nova, comportamento alterado, depreciações, remoções, correções e patches de segurança. Refatorações, mudanças de teste e edições de CI ficam no histórico do git.
As afirmações técnicas deste artigo não foram revisadas de forma independente. Se algo estiver errado, avise a gente e vamos corrigir.