Adaptar Changelog para Evitar Conflitos de Merge em Mudanças Simultâneas
Contexto
Atualmente, o changelog do projeto é mantido em um único arquivo, o que frequentemente causa conflitos de merge quando múltiplos colaboradores estão alterando o arquivo simultaneamente. Isso se torna especialmente problemático quando as alterações ocorrem nas mesmas categorias de mudanças (ex.: "features", "bug fixes"). O arquivo atual segue as diretrizes do Keep a Changelog e deve continuar seguindo essas diretrizes para garantir consistência e organização no histórico de mudanças.
Motivação
Para facilitar a colaboração no changelog e evitar conflitos de merge, precisamos de uma abordagem que permita que múltiplos colaboradores possam contribuir de forma independente, sem interferir nas mudanças dos outros. A solução deve ser eficiente, garantindo que o arquivo final de changelog seja bem estruturado e atualizado sem conflitos, e que o padrão atual seja mantido.
Propostas de Solução
Aqui estão duas soluções possíveis para resolver o problema de conflitos no changelog:
- Separação por arquivos
- Coleta de mudanças diretamente dos commits
1. Separar Changelog por Versão, Tipo de Mudança e Nome do Contribuidor
Como funciona:
- A estrutura do changelog seria organizada da seguinte maneira:
- Para cada versão, seria criada uma pasta por versão (ex.:
changelogs/v2.2.0/). - Dentro dessa pasta, seria criado um arquivo individual para cada tipo de mudança + usuário. O nome do arquivo incluiria o tipo de mudança e o nome do usuário responsável pela contribuição, como por exemplo:
changelogs/v2.2.0/add-camilamaia.md(para uma nova feature adicionada porcamilamaia)changelogs/v2.2.0/fix-joaosilva.md(para uma correção de bug feita porjoaosilva)
- Para cada versão, seria criada uma pasta por versão (ex.:
Vantagens dessa abordagem:
- Evita conflitos de merge 100%: Como cada contribuição seria feita em um arquivo separado, com um nome único para cada tipo de mudança e usuário, não haveria sobreposição de edições, mesmo se múltiplos colaboradores estiverem trabalhando nas mesmas categorias ou versões.
- Clareza no histórico de mudanças: As contribuições ficam claramente identificadas pela versão, tipo de mudança e usuário, facilitando o rastreamento e a revisão.
- Organização eficiente: O changelog ficaria estruturado de forma organizada por versão e tipo de mudança, garantindo que cada contribuição seja registrada de maneira clara.
Automação necessária:
- Criar uma automação (usando GitHub Actions) para consolidar os arquivos criados em uma versão em um único arquivo de changelog final, unificando as contribuições feitas para aquela versão.
- A automação poderia gerar ou atualizar o changelog final da versão, combinando as entradas de todos os arquivos na pasta correspondente (ex.:
changelogs/v2.2.0/), mantendo a ordem cronológica das mudanças.
2. Padronização de Commits e Automação para Verificar Mudanças no Changelog
Como funciona:
- A proposta é garantir que cada contribuição ao changelog seja identificada no commit com a padronização dos tipos de mudança e usuário.
- O commit que altera o changelog seguiria uma convenção de formato, como:
chore(changelog): add feature for v2.2.0 by @camilamaiafix(changelog): update bug fix for v2.2.0 by @joaosilva
Automação necessária:
- A automação verificaria os commits de merge no
main(principalmente os commits de squash) para garantir que as alterações no changelog sejam agrupadas corretamente na pasta e no arquivo correspondente à versão. - Quando um commit de merge for feito, a automação poderia verificar se o commit contém alterações no changelog e, se necessário, agrupar essas alterações na versão correta.
- A automação também poderia verificar a formatação dos commits para garantir que eles seguem o padrão estabelecido, garantindo a consistência e organização do changelog.
Vantagens dessa abordagem:
- Automação de merge e verificação de commits: A automação reduziria o risco de erros ao tentar combinar as mudanças feitas diretamente no repositório, garantindo que o changelog final seja consistente e sem sobreposições.
- Consistência no histórico de mudanças: Com a padronização, os commits ficam claros e facilmente rastreáveis, garantindo que o changelog final seja bem estruturado.
Desvantagens dessa abordagem:
- Dependência de padronização de commits: Todos os colaboradores precisariam seguir o padrão de commit rigorosamente, o que pode exigir algum esforço de adaptação.
- Necessidade de automação adicional: Além da padronização de commits, seria necessário configurar e manter a automação para verificar e organizar as contribuições ao changelog.
Passos
- Definir a melhor estratégia, podendo ser uma das abordagens propostas ou outra nova. Favor discutir a ideia aqui na issue antes da implementação.
- Implementar as automações necessárias.
- Testar as automações para garantir que estão funcionando corretamente.
- Garantir que o arquivo
CHANGELOG.mdpreserve o conteúdo gerado até então, mantendo o seu padrão atual, conforme as diretrizes do Keep a Changelog. Ou seja, o resultado final deve ser o mesmo, mas o processo de geração dele deve ser adaptado. - Atualizar as documentações de contribuição:
Links úteis
Outra alternativa seria adotar o Release Please, mantido pelo Google.
Como funciona
-
Ele lê mensagens de commit (ou labels de PR) que seguem Conventional Commits.
-
Com base nisso, gera automaticamente um PR de release contendo:
- O
CHANGELOG.mdatualizado. - O bump de versão do projeto (quando aplicável).
- O
-
Esse PR é revisado normalmente pelo time. Se necessário, o changelog pode ser editado manualmente dentro do PR antes do merge.
-
Ao dar merge, o bot cria a tag e o GitHub Release.
Como o PR é gerado
- Colocamos para dispará-lo em um workflow de GitHub Actions.
- Pode ser configurado para rodar manual (workflow_dispatch), por exemplo. Neste caso:
- Uma pessoa mantenedora clica em Run workflow.
- O bot olha os commits desde a última tag.
- Se houver mudanças relevantes (feat/fix/etc.), abre ou atualiza o PR de release.
- Se não houver, não faz nada.
Vantagens
- Evita conflitos no
CHANGELOG.md: ninguém edita namain, só o PR do bot altera. - Consistência: segue um padrão fixo (ex.: Keep a Changelog), evitando divergências de formatação.
- DX melhorado: quem contribui só precisa abrir PR com commit formatado ou label; não se preocupa com changelog.
- Customizável: é possível mapear tipos de commit para seções em português, preservando exatamente o estilo de changelog que já usamos hoje.
- Edição flexível: se for necessário, dá para ajustar o changelog dentro do PR do release antes de mergear.
Personalização para o nosso caso
-
O Release Please permite mapear tipos de commit (
feat,fix,docs,chore,refactor) para seções como### Added,### Fixed,### Documentation, etc. -
Assim, o changelog continua no formato Keep a Changelog, em português, com seções como:
## [Unreleased] ### Added - Utilitário `convert_code_to_uf` [#410](link) ### Deprecated - **BREAKING CHANGES** Suporte ao Python 3.8 [#561](link) -
Os prefixos de Conventional Commits (
feat,fix, etc.) precisam ser em inglês (exigência do parser), mas os textos e o changelog ficam em português. -
Os links de comparação no rodapé (
[2.2.0]: ...) são atualizados automaticamente.
Como evita conflitos
- O
CHANGELOG.mdnunca é editado manualmente namain. - Apenas o PR de release faz alterações no arquivo.
- Se alguém precisar corrigir formatação ou ajustar descrição, faz isso no PR do bot.
Fluxo do time
- Contribuidores abrem PR normalmente, sem tocar no changelog.
- Maintainers, quando acharem que é hora de fazer uma release, rodam o workflow manual.
- O Release Please abre/atualiza o PR de release.
- O time revisa e ajusta o changelog dentro do PR, se precisar.
- Merge do PR → tag + release publicados automaticamente.
Essa abordagem dá menos atrito para quem contribui, mantém nosso changelog no padrão Keep a Changelog e resolve definitivamente o problema de conflitos.
O quê acham?
Acho interessante a abordagem de usar fragmentos de changelog em arquivos separados e juntar tudo depois. Essa estratégia além de praticamente eliminar os conflitos de merge no changelog, como já foi falado pela @camilamaia ela possibilita o uso de ferramentas como o towncrier que tornam esse fluxo bem simples de adotar. O towncrier automatiza a junção dos fragmentos no changelog principal no momento da release.
Outra vantagem que vejo sobre as outras estratégias é que, usando fragmentos, a gente pode revisar e melhorar cada entrada do changelog antes dela ir para o arquivo final. Assim, garantimos que as mudanças fiquem bem explicadas e fáceis de entender para todo mundo, diferente das outras opções que só usam as mensagens dos commits. Se bem que o Release Please possibilita o review do PR de alteração do changelog também.
Acabei recebendo a dica dessa ferramenta aqui https://commitizen-tools.github.io/commitizen/:
About[¶](https://commitizen-tools.github.io/commitizen/#about)
Commitizen is a powerful release management tool that helps teams maintain consistent and meaningful commit messages while automating version management.
What Commitizen Does[¶](https://commitizen-tools.github.io/commitizen/#what-commitizen-does)
By enforcing standardized commit conventions (defaulting to [Conventional Commits](https://www.conventionalcommits.org/)), Commitizen helps teams:
Write clear, structured commit messages
Automatically manage version numbers using semantic versioning
Generate and maintain changelogs
Streamline the release process
Como já utilizamos o Conventional Commits na action do título do pr acho que ficaria mais fácil incorporar essa integração ao fluxo.
Já fiz alguns testes iniciais aqui pra validar essa ferramenta.
Fala, pessoal! Queria sugerir uma coisa sobre o CHANGELOG.
Como já usamos Conventional Commits (feat, fix, etc), podemos usar o git-cliff pra gerar o changelog automaticamente. Ele lê os commits e monta o arquivo pra gente.
A parte legal é que mantém o [Unreleased] sempre atualizado no próprio CHANGELOG.md. Mergeou um PR, atualiza sozinho. Todo mundo vê o que mudou desde a última versão. Na hora do release, cria a tag e ele converte o Unreleased pra versão nova.
Tecnicamente é simples: arquivo de config + workflow GitHub Actions que roda após merges na main. Pra release, mesmo comando manualmente.
https://github.com/orhun/git-cliff
Casamos isso com commitzen local e via PR, tudo fica quase 100% automatizado (só release que a gente escolhe quando sai)
Bora!
🇧🇷 Português ✅ Issue #469 atribuída a @morais90. Verifique o guia de contribuição para instruções sobre como submeter sua Pull Request.
🇬🇧 English ✅ Issue #469 assigned to @morais90. Check the contributing guide for instructions on submitting your Pull Request.