Changelogs em monorepo: um só, ou um por pacote?
6 min de leitura
Um monorepo abriga várias coisas lançadas separadamente dentro de um único repositório, e um changelog precisa primeiro responder uma pergunta: o leitor se importa com o repositório, ou se importa com um pacote específico dentro dele? A maioria dos times nunca decide isso de propósito. Começam com um changelog porque existe um repositório, vão adicionando pacotes com o tempo, e acabam com um log em que alguém usando a CLI precisa rolar por quarenta entradas do backend sem relação nenhuma até achar a que lançou a correção dele. O que decide a forma certa não é a estrutura do repositório, e sim quem lê o log e o que essa pessoa já sabe que está procurando.
O que faz o changelog de um monorepo ser diferente do de um repositório único?
Um changelog de repositório único tem um público implícito: todo mundo que usa a única coisa que esse repositório constrói. O público de um monorepo se divide por pacote, e pacotes no mesmo repositório muitas vezes são lançados em cronogramas diferentes, para consumidores diferentes, em níveis de estabilidade diferentes. Uma biblioteca publicada em um registro e uma ferramenta administrativa interna podem viver no mesmo monorepo e não ter quase nada em comum para quem lê o changelog.
| Formato do repositório | Leitor típico | Changelog que combina |
|---|---|---|
| Um único app lançado | Todo mundo que usa o produto | Um log, para o repositório inteiro |
| Workspace de bibliotecas (vários pacotes publicados) | Quem depende de um pacote específico | Um log por pacote |
| App mais ferramentas internas | Dois públicos diferentes sem sobreposição | Dividido por público, não por pasta |
| App mais o próprio SDK | Usuários do produto, e integradores do SDK | Dois logs: um do produto, um do SDK |
Todo pacote precisa do próprio changelog?
Só os que têm um público independente. Um pacote publicado em um registro precisa do próprio log,
porque quem instala não tem motivo nenhum para ler qualquer outra coisa no repositório, e as
ferramentas de release para monorepo como Lerna e Changesets escrevem um
CHANGELOG.md por pacote, ao lado do package.json dele. Um utilitário interno com um único consumidor, o app
que já vive no mesmo repositório, não precisa de um log separado; incluir as mudanças dele nas
entradas desse app é mais útil do que um segundo arquivo que ninguém fora do time abre.
O teste é o mesmo que decide se qualquer entrada pertence a um changelog: o leitor notaria ou se importaria, e consegue agir sabendo disso. Aplique isso por pacote, não por pasta, e um repositório com doze pacotes pode acabar com dois changelogs de verdade e dez pacotes que simplesmente não precisam de um.
Como saber qual pacote causou qual entrada de changelog?
Marque cada entrada com o pacote dela no momento em que é escrita, não depois inspecionando quais arquivos um commit tocou. Um commit que corrige uma biblioteca interna compartilhada pode produzir uma entrada de changelog em cada pacote que depende dela, e os caminhos dos arquivos sozinhos não conseguem dizer qual dessas entradas a jusante o leitor realmente precisa ver; só uma pessoa decidindo “isso é visível para quem usa o pacote A e não para quem usa o pacote B” consegue fazer isso. Conventional commits ajudam aqui mecanicamente, nomeando o pacote em cada commit, mas o escopo ainda assim só produz um rascunho. A mesma regra de duas camadas daquele artigo se aplica por pacote: um rascunho com o escopo certo ainda precisa de uma passada humana antes de ser formulado para o leitor real daquele pacote.
O que um changelog compartilhado precisa que um de repositório único não precisa?
Uma etiqueta de pacote em cada entrada, logo no início, antes da descrição, para que um leitor percorrendo o log consiga, em uma única passada, pular tudo que não é dele. Sem essa etiqueta, um log compartilhado se lê como um feed aleatório, e um leitor interessado em um pacote não tem como filtrá-lo além de memorizar quais linhas contam, o que ninguém faz depois da primeira semana.
## 2026-09-07
### [cli] Adicionado
- `acme push --dry-run` mostra o que seria enviado sem
enviar de fato.
### [core] Corrigido
- O backoff de novas tentativas não é mais reiniciado em uma
requisição bem-sucedida que retorna um corpo vazio.
Duas entradas, dois públicos, um olhar para distingui-las. Um fluxo de trabalho no estilo Changesets integra essa marcação diretamente no processo de lançamento: quem contribui escreve uma nota curta, com o escopo do pacote, ao lado da própria mudança, e a ferramenta monta os changelogs por pacote e os saltos de versão a partir dessas notas no momento do lançamento, em vez de tentar reconstruir os limites dos pacotes depois, a partir de um histórico de commits já unificado.
Como o versionamento se relaciona com um changelog de monorepo?
Pacotes versionados de forma independente precisam do próprio changelog porque têm o próprio número de versão, e um changelog compartilhado não consegue expressar “o pacote A foi de 2.1 para 2.2 enquanto o pacote B ficou em 1.4” sem virar dois logs dentro de um único arquivo. Semantic versioning e o seu changelog cobre como o número de versão em si deveria mapear para as categorias de changelog; em um monorepo, esse mapeamento precisa ser aplicado por pacote, porque uma mudança que quebra em um pacote não é uma mudança que quebra para um pacote irmão que não depende dele.
Um repositório que lança um produto como uma única unidade implantável, mesmo que construído a partir de muitos pacotes internos, não tem esse problema: os pacotes compartilham uma versão porque sempre são lançados juntos, e um único changelog é o correto.
Como as tags do git se encaixam em um monorepo?
A mesma regra de tags do git, lançamentos e o seu changelog
se aplica, por pacote: um pacote com a própria versão precisa do próprio prefixo de tag,
tipicamente nome-do-pacote@1.4.0 em vez de um v1.4.0 nu que não consegue dizer a qual pacote
pertence. Um monorepo marcado só com números de versão nus não consegue responder depois “o que
tinha em core quando o cli lançou a 2.2”, porque nada no disco registra a qual pacote essa tag
realmente pertencia.
FAQ
Preciso de um changelog separado para cada pacote em um monorepo? Só para pacotes com público independente, geralmente qualquer coisa publicada em um registro. Um pacote com um único consumidor interno que já vive no mesmo repositório pode entrar no log desse consumidor em vez de manter um próprio.
O que marca uma entrada de changelog com o pacote certo? A pessoa que escreve a entrada, no momento em que a escreve, não uma varredura automática dos caminhos de arquivo alterados. Uma mudança em uma biblioteca compartilhada pode produzir uma entrada diferente em cada pacote que depende dela, e só um humano consegue decidir o que cada uma dessas entradas a jusante deveria realmente dizer.
Um monorepo deveria usar um único número de versão para tudo? Só se cada pacote sempre for lançado junto com os outros. Se os pacotes forem publicados de forma independente algum dia, eles precisam de versões independentes, e versões independentes precisam de changelogs independentes para fazer sentido.
Uma ferramenta de changelog para monorepo substitui a etapa de edição humana? Não. Ferramentas como o Changesets automatizam a coleta e a montagem das notas por pacote no momento do lançamento; a nota em si, escrita na linguagem do leitor em vez da de quem contribuiu, continua sendo trabalho de uma pessoa, assim como em qualquer outro pipeline de changelog.
As afirmações técnicas deste artigo não foram revisadas de forma independente. Se algo estiver errado, avise a gente e vamos corrigir.