Todos os artigos
175 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Comparativos

Branching strategies: Git Flow, trunk-based e GitHub Flow

Branching strategies: compare Git Flow, trunk-based e GitHub Flow e evite os erros mais comuns ao escolher um fluxo para o seu time.

Branching strategies: Git Flow, trunk-based e GitHub Flow
COVER · Comparativos

O time que se afogou em branches

Já entrei num projeto onde existiam 47 branches abertas ao mesmo tempo. develop, release/2.3, release/2.4, hotfix/login, dezenas de feature branches paradas há semanas, e ninguém sabia ao certo o que estava em produção. Toda merge era uma rodada de roleta-russa: você puxava develop, rezava, e perdia meia tarde resolvendo conflito de coisa que outra pessoa mexeu duas semanas atrás. O problema nunca foi o Git. Foi a branching strategy errada para o contexto daquele time.

Aqui eu comparo os três fluxos que dominam a discussão — Git Flow, GitHub Flow e trunk-based — e o que cada um exige do seu time. Se a sua dor de cabeça hoje é o resultado disso (merges enormes que viram um campo minado de conflito), o caminho para sair do buraco passa por resolver conflitos de merge sem pânico primeiro, e depois adotar um fluxo que não os recrie toda semana.

Git Flow: pesado, e quase nunca o que você quer

Git Flow é a estratégia que a maioria das pessoas aprende primeiro e abandona depois. O modelo tem main (produção), develop (integração), feature branches saindo de develop, release branches para estabilizar uma versão e hotfix branches saindo de main. É um fluxo desenhado para software versionado e com releases discretos: um app desktop, uma biblioteca distribuída, firmware, qualquer coisa onde "a versão 2.4" é uma entidade real que vive em paralelo com a 2.3 ainda em suporte.

O custo é alto. Você mantém duas branches de longa vida (main e develop) que divergem o tempo todo, e cada release vira uma cerimônia de merge. Em produto web com deploy contínuo, isso é puro overhead: você não tem "versão 2.4", você tem o que está em produção agora. A branch develop vira um limbo onde código fica acumulando dias antes de chegar ao usuário, e quanto mais tempo uma branch vive longe da main, pior o conflito quando ela finalmente volta.

Minha opinião sem rodeios: se você está fazendo SaaS ou web app e usa Git Flow, provavelmente está pagando um imposto de complexidade que não precisa pagar.

GitHub Flow: uma main e branches de vida curta

GitHub Flow é o oposto da burocracia. Existe uma única branch de longa vida, a main, que está sempre deployável. Para qualquer trabalho, você cria uma branch curta a partir da main, faz seus commits, abre um Pull Request, passa pelo review e CI, e faz merge de volta. A branch some logo depois. É isso.

git switch -c fix/timezone-no-relatorio
# commits...
git push -u origin fix/timezone-no-relatorio
# abre PR, review + CI verde, merge, deleta a branch

O segredo é o tamanho da branch. Vida curta significa de horas a poucos dias — não semanas. Quando a branch vive pouco, ela diverge pouco da main, e divergência pequena é conflito pequeno. O PR também vira a unidade natural de revisão e o gatilho do seu pipeline: testes rodam no PR, e o merge na main dispara o deploy. Para a maioria dos times de web, esse é o ponto ideal — baixo cerimonial, deploy frequente, histórico legível.

A armadilha clássica é deixar uma branch "feature grande" viver por três semanas. Aí você reinventou o pior do Git Flow sem o benefício dele. Se a feature é grande, quebre em PRs menores que vão para a main atrás de uma feature flag.

Trunk-based: commitar direto na main, com disciplina

Trunk-based development empurra a ideia ao limite: todo mundo integra na main (o "trunk") várias vezes ao dia, com branches que vivem horas no máximo — ou nenhuma branch. Código incompleto entra em produção desligado por uma feature flag e é ligado quando estiver pronto.

if feature_flags.enabled("novo_checkout", user):
    return novo_checkout(request)
return checkout_legado(request)

Isso elimina por construção a categoria inteira de "merge hell": não existe branch de longa vida para divergir. Mas tem um pré-requisito não-negociável: maturidade de CI. Você precisa de uma suíte de testes rápida e confiável rodando em cada commit, porque a main está sempre a um push de ir para produção. Sem isso, trunk-based é uma forma elegante de quebrar a produção três vezes por dia.

Feature flags também cobram seu preço — são código condicional que precisa ser limpo depois, ou você acumula débito de flags mortas. Mas para times com CI sério e cultura de testes, trunk-based dá o ciclo mais rápido entre escrever código e ele chegar no usuário.

Como escolher de verdade

Esqueça qual fluxo é "moderno". Escolha pela natureza do que você entrega e pela maturidade do time:

  • Você versiona releases discretos (lib, desktop, firmware, suporte a múltiplas versões em paralelo): Git Flow ainda faz sentido. O overhead existe porque o problema é genuinamente complexo.
  • Você faz web/SaaS com deploy contínuo e quer simplicidade: GitHub Flow. Branch curta, PR, merge. Funciona para 90% dos times.
  • Você tem CI rápido e confiável, cultura de testes e quer o ciclo mais curto possível: trunk-based com feature flags.

O eixo que importa mais que o nome do fluxo é o tempo de vida das branches. Quanto mais curtas, menos conflito, deploy mais frequente, review mais fácil. Toda branching strategy boa é, no fundo, uma desculpa para manter branches curtas. As ruins são as que incentivam código a ficar parado longe da main.

Perguntas frequentes

Git Flow está morto?

Não, mas o escopo dele encolheu. Para software versionado com múltiplas versões em suporte simultâneo, o modelo continua resolvendo um problema real. Para web app com deploy contínuo, ele virou overhead — e é por isso que a maioria dos times migrou para GitHub Flow ou trunk-based.

Trunk-based não é arriscado demais?

O risco vem da falta de CI, não da estratégia. Com uma suíte de testes rápida, confiável e feature flags, commitar na main várias vezes ao dia é mais seguro do que mergear uma branch gigante de três semanas. O perigo real é adotar trunk-based sem ter a maturidade de testes que ele exige.

Qual a diferença prática entre GitHub Flow e trunk-based?

GitHub Flow ainda usa branches curtas com PR antes de chegar na main. Trunk-based reduz isso ao mínimo: branches de horas ou commit direto, com integração contínua na main e código incompleto escondido atrás de flags. É uma questão de grau — trunk-based é GitHub Flow levado ao extremo da integração contínua.

Posso misturar estratégias?

Pode, e muitos times fazem isso sem nem perceber. Um time pode rodar GitHub Flow no dia a dia e abrir uma release branch só quando precisa estabilizar algo crítico. O problema é misturar sem critério e acabar com develop, release e PRs convivendo sem regra clara — aí você tem o pior dos dois mundos.

O que levar para o seu time

A pergunta certa não é "qual a melhor branching strategy", é "qual fluxo mantém as nossas branches curtas dado o que entregamos". Git Flow para releases versionados, GitHub Flow para o caso comum de web com deploy contínuo, trunk-based para times maduros que querem o ciclo mais curto. Em todos eles, o inimigo é a branch de longa vida que diverge da main e transforma cada merge num campo minado. Escolha o fluxo mais simples que o seu contexto suporta, mantenha as branches curtas, e a maior parte da dor de merge desaparece sozinha.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil