DevOps & CI/CD

Como Usar Estratégias de Branching: Git Flow, Trunk-Based e GitHub Flow em Produção

17 min de leitura

Como Usar Estratégias de Branching: Git Flow, Trunk-Based e GitHub Flow em Produção

Introdução ao Versionamento de Código e Estratégias de Branching Quando você trabalha em um projeto de software, especialmente em equipe, precisa de um sistema robusto para organizar como o código é desenvolvido, testado e entregue ao usuário final. Git é a ferramenta de controle de versão mais utilizada atualmente, mas Git sozinho não define como você organiza seus branches. É aí que entram as estratégias de branching: metodologias que definem quando criar uma branch, como nomeá-la, quando fazer merge e quem pode fazer isso. Nos próximos anos de carreira, você verá três estratégias dominando a indústria: Git Flow, Trunk-Based Development e GitHub Flow. Cada uma tem seus pontos fortes e foi criada para resolver problemas específicos. Não existe uma "melhor" — existe a mais apropriada para seu contexto de desenvolvimento. Vamos estudá-las em profundidade. Git Flow: Estrutura Formal para Projetos com Ciclos de Release O Conceito Central Git Flow foi proposto por Vincent Driessen em 2010 e se tornou padrão

<h2>Introdução ao Versionamento de Código e Estratégias de Branching</h2>

<p>Quando você trabalha em um projeto de software, especialmente em equipe, precisa de um sistema robusto para organizar como o código é desenvolvido, testado e entregue ao usuário final. Git é a ferramenta de controle de versão mais utilizada atualmente, mas Git sozinho não define como você <em>organiza</em> seus branches. É aí que entram as estratégias de branching: metodologias que definem quando criar uma branch, como nomeá-la, quando fazer merge e quem pode fazer isso.</p>

<p>Nos próximos anos de carreira, você verá três estratégias dominando a indústria: Git Flow, Trunk-Based Development e GitHub Flow. Cada uma tem seus pontos fortes e foi criada para resolver problemas específicos. Não existe uma &quot;melhor&quot; — existe a mais apropriada para seu contexto de desenvolvimento. Vamos estudá-las em profundidade.</p>

<h2>Git Flow: Estrutura Formal para Projetos com Ciclos de Release</h2>

<h3>O Conceito Central</h3>

<p>Git Flow foi proposto por Vincent Driessen em 2010 e se tornou padrão em empresas que trabalham com ciclos de release bem definidos. A ideia principal é simples: separar desenvolvimento contínuo de preparação para produção usando branches dedicadas. Você não trabalha diretamente na <code>main</code> — essa branch é sagrada, reservada apenas para versões que estão em produção.</p>

<p>O Git Flow define cinco tipos de branch: <code>main</code> (produção), <code>develop</code> (integração de desenvolvimento), <code>feature/<em></code> (novas funcionalidades), <code>release/</em></code> (preparação para release) e <code>hotfix/*</code> (correções urgentes em produção). Essa separação clara reduz o risco de código quebrado chegar ao usuário final, mas exige disciplina e processos bem estruturados.</p>

<h3>Fluxo Prático e Nomenclatura</h3>

<p>Quando você precisa desenvolver uma nova funcionalidade em Git Flow, você cria uma branch <code>feature/</code> a partir de <code>develop</code>. Por exemplo, se está desenvolvendo autenticação de dois fatores, você criaria <code>feature/two-factor-auth</code>. O nome é descritivo e segue padrão em toda a equipe.</p>

<pre><code class="language-bash"># Você está em develop (sempre atualizada com o servidor)

git checkout develop

git pull origin develop

Criar a branch de feature

git checkout -b feature/two-factor-auth

Fazer commits conforme desenvolveu a funcionalidade

git commit -m &quot;Implementar geração de código TOTP&quot;

git commit -m &quot;Adicionar validação de código temporário&quot;

git commit -m &quot;Criar testes unitários para TOTP&quot;

Enviar para servidor (para backup e code review)

git push origin feature/two-factor-auth</code></pre>

<p>Quando a funcionalidade está pronta e testada localmente, você abre um Pull Request no GitHub/GitLab. Um colega revisa, sugere melhorias, e após aprovação, você faz merge para <code>develop</code>. A branch de feature é deletada — ela cumpriu seu papel.</p>

<h3>Release e Hotfix: Cenários Reais</h3>

<p>Conforme funcionalidades se acumulam em <code>develop</code>, você chega a um ponto onde deseja fazer uma versão estável. Aqui entra a branch <code>release/</code>. Você cria <code>release/1.5.0</code> a partir de <code>develop</code>, testa intensamente, corrige bugs menores e, quando tudo está perfeito, faz merge para <code>main</code> e tag com a versão.</p>

<pre><code class="language-bash"># Criar branch de release

git checkout -b release/1.5.0 develop

git push origin release/1.5.0

Nessa branch, você APENAS corrige bugs

Adicionar patch version se necessário

git tag -a v1.5.0 -m &quot;Release version 1.5.0&quot;

git push origin v1.5.0

Fazer merge para main e develop

git checkout main

git merge --no-ff release/1.5.0

git push origin main

git checkout develop

git merge --no-ff release/1.5.0

git push origin develop

Deletar branch local e remota

git branch -d release/1.5.0

git push origin --delete release/1.5.0</code></pre>

<p>Quando um bug crítico é descoberto em produção, você não espera pela próxima release. Cria <code>hotfix/</code> direto de <code>main</code>, corrige, testa e faz merge para <code>main</code> e <code>develop</code>. Isso garante que a correção não se perca.</p>

<h2>Trunk-Based Development: Simplicidade e Integração Contínua</h2>

<h3>Filosofia: Uma Única Verdade</h3>

<p>Trunk-Based Development é o oposto do Git Flow em filosofia. Aqui, há basicamente uma única branch chamada <code>main</code> (ou <code>master</code>), e todos os desenvolvedores fazem commits pequenos e frequentes diretamente nela ou em branches de vida <em>muito</em> curta — horas, não dias. A ideia vem dos primórdios do controle de versão, quando a facilidade de branching não existia e a disciplina era fundamental.</p>

<p>Essa abordagem funciona excepcionalmente bem com Integração Contínua (CI) robusto. Se você commita code quebrado, os testes automatizados pegam em minutos. Não há como código ruim ficar escondido em uma branch de feature por semanas. Isso força qualidade desde o primeiro commit.</p>

<h3>Prática: Feature Flags e Pequenos Passos</h3>

<p>Como você desenvolveria uma grande funcionalidade em Trunk-Based sem quebrar a <code>main</code>? Resposta: Feature Flags (ou Feature Toggles). Você escreve o código novo dentro de uma condição que está desativada por padrão. Testes passam, código é integrado à <code>main</code> no dia seguinte, mas a funcionalidade não aparece para usuários até estar 100% pronta.</p>

<pre><code class="language-python"># Código em Trunk-Based Development com Feature Flag

import os

from typing import Optional

def calculate_discount(user_id: int, amount: float) -&gt; float:

&quot;&quot;&quot;Calcula desconto, com nova lógica ainda em desenvolvimento.&quot;&quot;&quot;

base_discount = amount * 0.05

Feature flag para novo algoritmo de desconto

use_ml_discount = os.getenv(&#039;FEATURE_ML_DISCOUNT_ENABLED&#039;, &#039;false&#039;).lower() == &#039;true&#039;

if use_ml_discount:

Nova funcionalidade em homologação

return apply_ml_discount(user_id, amount)

else:

Comportamento estável de produção

return base_discount

def apply_ml_discount(user_id: int, amount: float) -&gt; float:

&quot;&quot;&quot;Novo algoritmo que usa ML para descontos personalizados.&quot;&quot;&quot;

Chamada a modelo que está em teste

predicted_discount = ml_model.predict(user_id=user_id, amount=amount)

return max(amount * 0.05, predicted_discount)

Teste que passa independente da flag

def test_discount_calculation():

result = calculate_discount(user_id=123, amount=100.0)

assert result &gt; 0

A funcionalidade nova só é testada quando a flag está ON

os.environ[&#039;FEATURE_ML_DISCOUNT_ENABLED&#039;] = &#039;true&#039;

result_ml = calculate_discount(user_id=123, amount=100.0)

assert result_ml &gt; 0</code></pre>

<h3>Branching Minimizado com Integração Rápida</h3>

<p>Em Trunk-Based, quando você precisa trabalhar em algo, cria uma branch, mas apenas localmente enquanto está desenvolvendo. Você commita em <code>main</code> ao menos uma vez por dia. Se trabalhar em par ou em uma equipe pequena, às vezes você nem cria branch — trabalha direto em <code>main</code> com grande disciplina.</p>

<pre><code class="language-bash"># Workflow típico em Trunk-Based

git checkout main

git pull origin main

Trabalhar localmente, fazer vários commits

git add src/payment/processor.py

git commit -m &quot;Refatorar lógica de pagamento para handlers&quot;

git add tests/

git commit -m &quot;Adicionar testes para novo payment handler&quot;

Rodar testes localmente ANTES de push

pytest tests/ -v

mypy src/ --strict

Se tudo passar, integrar à main imediatamente

git push origin main

CI/CD pipeline roda automaticamente no servidor</code></pre>

<p>O código que você pushá será testado por testes automatizados em segundos. Se quebrar, toda a equipe sabe (CI falha para todos). Isso cria uma cultura de responsabilidade compartilhada.</p>

<h2>GitHub Flow: O Meio do Caminho para Equipes Ágeis</h2>

<h3>Estrutura Leve com Code Review Obrigatório</h3>

<p>GitHub Flow foi criado pelo GitHub como simplificação do Git Flow, ideal para equipes que fazem deploy contínuo mas ainda querem formalidade. A estrutura é extremamente simples: <code>main</code> sempre está pronta para produção, você cria branches descritivas para qualquer mudança, faz Pull Request (PR), discute e revisa o código, e depois faz merge.</p>

<p>Diferentemente de Git Flow, não há branches de <code>release</code> ou <code>hotfix</code> — tudo segue o mesmo fluxo. Diferentemente de Trunk-Based, as branches vivem mais tempo (dias, não horas) e o code review é <em>obrigatório</em> antes de qualquer merge. Isso oferece proteção sem sacrificar a agilidade.</p>

<h3>Fluxo Prático em um Projeto Real</h3>

<p>Imagine que você trabalha em uma API REST e precisa adicionar suporte a autenticação via OAuth2. Seu workflow seria:</p>

<pre><code class="language-bash"># 1. Começar a partir de main atualizada

git checkout main

git pull origin main

2. Criar branch descritiva

git checkout -b add/oauth2-authentication

3. Desenvolver, fazer commits legíveis

git add src/auth/oauth2.py

git commit -m &quot;Implementar cliente OAuth2 com suporte a Google e GitHub&quot;

git add tests/auth/test_oauth2.py

git commit -m &quot;Adicionar testes para fluxo de autenticação OAuth2&quot;

git add docs/AUTH.md

git commit -m &quot;Documentar integração OAuth2 para novos desenvolvedores&quot;

4. Enviar branch para servidor

git push origin add/oauth2-authentication</code></pre>

<p>Agora no GitHub/GitLab, você abre um Pull Request. A descrição é clara: explica o problema que resolve, como testar, e se há migrations ou mudanças de configuração. Seus colegas comentam, sugerem mudanças. Você commita as correções sugeridas — elas aparecem automaticamente no PR.</p>

<pre><code class="language-bash"># Feedback recebido: &quot;Falta tratamento de erro para token expirado&quot;

git add src/auth/oauth2.py

git commit -m &quot;Tratar tokens OAuth2 expirados com refresh automático&quot;

git push origin add/oauth2-authentication

PR atualiza automaticamente</code></pre>

<p>Quando está tudo aprovado (e testes CI passaram), você faz merge. A branch é deletada automaticamente, e seu código vai para <code>main</code>. Se houver deploy automático, sua mudança está em produção em minutos.</p>

<h3>Proteção de Branch e Automação</h3>

<p>GitHub Flow se beneficia muito de regras de proteção de branch. Você configura que <code>main</code> exige no mínimo 1 aprovação de PR, testes CI devem passar, e não permite push direto. Isso garante que nada chega a produção sem revisão.</p>

<pre><code class="language-yaml"># Exemplo de configuração em GitHub (arquivo .github/branch-protection-rules.json)

{

&quot;pattern&quot;: &quot;main&quot;,

&quot;required_pull_request_reviews&quot;: {

&quot;required_approving_review_count&quot;: 1,

&quot;dismiss_stale_reviews&quot;: true,

&quot;require_code_owner_reviews&quot;: false

},

&quot;required_status_checks&quot;: {

&quot;strict&quot;: true,

&quot;contexts&quot;: [&quot;tests&quot;, &quot;linting&quot;, &quot;security-scan&quot;]

},

&quot;enforce_admins&quot;: false,

&quot;allow_force_pushes&quot;: false,

&quot;allow_deletions&quot;: false

}</code></pre>

<h2>Comparação e Quando Usar Cada Uma</h2>

<h3>Git Flow: Projetos com Releases Agendadas</h3>

<p>Use Git Flow quando você trabalha em um software que tem versões bem definidas e ciclos de release longos (2 semanas, 1 mês). Exemplos: aplicativos mobile distribuídos na App Store, software enterprise com contratos de suporte atrelados a versões específicas. O Git Flow brilha em controle — você sabe exatamente qual código está em cada versão.</p>

<p>A desvantagem é complexidade. Com muitos branches e merges, é fácil perder rastreabilidade. Além disso, é mais lento — você não consegue fazer deploy frequente de pequenas mudanças.</p>

<h3>Trunk-Based: Equipes Maduras com CI/CD Forte</h3>

<p>Escolha Trunk-Based quando você tem confiança em testes automatizados e deploy contínuo está no DNA da empresa. Gigantes de tech como Google, Netflix e Amazon usam variações disso. Você consegue fazer deploy várias vezes por dia, o código é mais limpo (menos merge conflicts), e toda a equipe trabalha em sincronia.</p>

<p>A desvantagem é que exige disciplina feroz. Um commit quebrado queima o CI para todos. Desenvolvedores juniores podem causar danos facilmente. Não recomendo para equipes pequenas ou com pessoas iniciantes.</p>

<h3>GitHub Flow: A Escolha Padrão Moderna</h3>

<p>GitHub Flow é o &quot;goldilocks&quot; — nem muito simples, nem muito complexo. Funciona bem para startups, equipes distribuídas, e projetos de todos os tamanhos. Você tem formalidade (code review obrigatório) mas agilidade (deploy frequente). A maioria das equipes modernas usa isso ou variações.</p>

<p>Use GitHub Flow se você está indeciso. É praticamente impossível errar com essa escolha.</p>

<h3>Tabela Comparativa</h3>

<div class="table-wrap"><table><thead><tr><th>Aspecto</th><th>Git Flow</th><th>Trunk-Based</th><th>GitHub Flow</th></tr></thead><tbody><tr><td><strong>Branches</strong></td><td>Muitas (feature, develop, release, hotfix, main)</td><td>Uma (main) + branches curtas</td><td>Poucas (main + feature branches)</td></tr><tr><td><strong>Ciclo de Release</strong></td><td>Planejado, versões definidas</td><td>Contínuo, deploy a qualquer momento</td><td>Contínuo com revisão</td></tr><tr><td><strong>Curve de Aprendizado</strong></td><td>Média-Alta</td><td>Alta</td><td>Baixa</td></tr><tr><td><strong>Adequado para Iniciantes</strong></td><td>Sim</td><td>Não</td><td>Sim</td></tr><tr><td><strong>Frequência de Deploy</strong></td><td>Baixa (semanal/mensal)</td><td>Muito Alta (diária)</td><td>Alta (diária/semanal)</td></tr><tr><td><strong>Risco de Conflitos</strong></td><td>Alto (muitos merges)</td><td>Baixo (integração rápida)</td><td>Médio</td></tr></tbody></table></div>

<h2>Conclusão</h2>

<p>Você aprendeu que estratégias de branching não são ornamentação — são estruturas que definem como sua equipe colabora, como código é validado, e como bugs não chegam a produção. <strong>Primeiro ponto importante</strong>: cada estratégia nasceu para resolver um problema específico, e a escolha certa depende do contexto (equipe, ciclo de release, maturidade de CI/CD).</p>

<p><strong>Segundo ponto</strong>: Git Flow é formalidade demais para equipes ágeis modernas; Trunk-Based exige excelência técnica que nem todas equipes têm; GitHub Flow é o ponto de equilíbrio e deve ser sua primeira escolha. <strong>Terceiro ponto</strong>: nenhuma estratégia funciona sem disciplina — seja code review rigoroso, testes automatizados confiáveis ou commits bem estruturados. A estratégia é só a moldura; a qualidade do trabalho dentro dela é o que importa.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://nvie.com/posts/a-successful-git-branching-model/" target="_blank" rel="noopener noreferrer">A Successful Git Branching Model - Vincent Driessen</a></li>

<li><a href="https://guides.github.com/introduction/flow/" target="_blank" rel="noopener noreferrer">GitHub Flow - GitHub Docs</a></li>

<li><a href="https://trunkbaseddevelopment.com/" target="_blank" rel="noopener noreferrer">Trunk Based Development - Paul Hammant</a></li>

<li><a href="https://martinfowler.com/articles/continuousIntegration.html" target="_blank" rel="noopener noreferrer">Continuous Integration - Martin Fowler</a></li>

<li><a href="https://martinfowler.com/articles/feature-toggles.html" target="_blank" rel="noopener noreferrer">Feature Toggles (aka Feature Flags) - Pete Hodgson</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em DevOps & CI/CD

Dominando Horizontal Pod Autoscaler e Vertical Pod Autoscaler em Kubernetes em Projetos Reais
Dominando Horizontal Pod Autoscaler e Vertical Pod Autoscaler em Kubernetes em Projetos Reais

Entendendo Autoscaling em Kubernetes Autoscaling é um dos pilares da infraest...

Dominando GitHub Actions Avançado: Matrix Builds, Environments e OIDC em Projetos Reais
Dominando GitHub Actions Avançado: Matrix Builds, Environments e OIDC em Projetos Reais

Matrix Builds: Executando Testes em Múltiplas Configurações A funcionalidade...

ConfigMaps e Secrets em Kubernetes: Gerenciando Configuração na Prática
ConfigMaps e Secrets em Kubernetes: Gerenciando Configuração na Prática

ConfigMaps e Secrets em Kubernetes: Gerenciando Configuração Quando você trab...