Pular para o conteúdo

Trunk-based vs GitFlow

Intermediário16 min de leituraversionamento

A estratégia de branch parece uma decisão de estilo e é, na prática, uma decisão sobre tamanho de lote. Branch longa é integração adiada; integração adiada é conflito grande, teste que só roda no fim e deploy assustador. Quase todo problema atribuído a “cultura de deploy” começa aqui.

Ela responde três perguntas: com que frequência o código de pessoas diferentes se encontra, quanto tempo uma mudança fica sem ser exercitada em conjunto, e quão fácil é responder “o que exatamente está em produção?”.

Repare que “quando a funcionalidade fica visível para o usuário” não está na lista. Isso é decisão de release, e a confusão entre as duas é o que mantém tanta gente presa a branch de longa duração.

O GitFlow (develop, feature/*, release/*, hotfix/*, main) foi descrito em 2010, para software com versões distribuídas — instalador, cliente desktop, versões antigas suportadas ao mesmo tempo. Para esse contexto, ele continua fazendo sentido.

Para um serviço web com deploy contínuo, o custo aparece rápido:

  • Duas branches permanentes que divergem, e merges grandes entre elas.
  • Branch de release que vira ambiente paralelo, com correção que precisa voltar para develop (e às vezes não volta).
  • Conflitos proporcionais ao tempo que a feature ficou aberta.
  • “O que está em produção?” exige investigação.

Se o seu produto é um serviço que você atualiza várias vezes por semana, GitFlow está resolvendo um problema que você não tem — e cobrando por isso todo dia.

Uma branch principal sempre entregável. Cada pessoa trabalha em branch curta (horas a dois dias), integra no tronco, e o tronco vai para produção com frequência.

Janela do terminal
git switch -c ajuste-timeout-checkout # branch de vida curta
# ... commits pequenos ...
git fetch origin && git rebase origin/main # integre cedo, resolva conflito pequeno
git push -u origin ajuste-timeout-checkout # PR pequeno, revisão rápida, merge no dia

O que isso exige para funcionar (e não é opcional):

  • Suíte de testes confiável rodando em cada PR — o tronco precisa ficar sempre verde.
  • Revisão rápida. PR pequeno esperando dois dias destrói a premissa.
  • Deploy automatizado e reversível.
  • Feature flags para separar entrega de liberação.

Se o time não tem isso, comece por aí. Adotar trunk-based sem teste automatizado transforma o tronco em campo minado.

A funcionalidade incompleta entra em produção desligada. O código integra todo dia; a liberação vira uma decisão independente, e a reversão vira um clique em vez de um deploy.

if flags.ativo("checkout-v2", usuario=usuario):
return checkout_v2(pedido)
return checkout_v1(pedido)

O preço é disciplina de limpeza: flag esquecida é dívida técnica que se multiplica (duas flags = quatro caminhos). Registre dono e data de remoção junto com a flag, e trate flag vencida como bug.

Situação Estratégia
Serviço web, deploy contínuo Trunk-based com branches curtas
Time pequeno, produto único Trunk-based, quase sem cerimônia
Versões suportadas em paralelo (SDK, on-premise) Branch por versão suportada
Regulado, com janela de release aprovada Trunk-based + branch de release curta, só para estabilização
Open source com colaboração externa Fork + PR (o fluxo do GitHub)

Repare que quase tudo cabe em trunk-based com pequenas variações. A pergunta útil não é “qual modelo adotamos?”, e sim “quanto tempo uma mudança fica fora do tronco?”. Se a resposta passa de dois dias, o modelo é o menor dos problemas.

  • Proteja o tronco: revisão obrigatória, verificações verdes, sem push --force.
  • Branch nomeada com o contexto (ajuste-timeout-checkout, não fix2).
  • Merge só com o tronco atualizado por baixo.
  • Apague a branch depois do merge — lista com duzentas branches é ruído.
  • Tag no que foi para produção, para responder “o que está rodando?” em segundos.

Próximo passo: faça o histórico trabalhar por você em Commits que geram changelog.