O Git oferece branches, mas não diz como usá-las. Em uma equipe pequena sem convenção, rapidamente surgem dúvidas: onde fica o código que vai para produção? Como se trabalha em duas funcionalidades ao mesmo tempo? O que acontece quando um bug crítico precisa ser corrigido enquanto uma nova versão ainda está em desenvolvimento?
O Git Flow é um modelo de organização de branches que responde a essas perguntas. Foi proposto por Vincent Driessen em 2010 e se tornou um dos padrões mais adotados pela indústria. Não é o único modelo — existem alternativas como GitHub Flow e Trunk-Based Development — mas o Git Flow é o mais completo para entender os princípios antes de avaliar as alternativas.
As Cinco Branches do Git Flow
O modelo define dois tipos de branches: as permanentes, que existem durante toda a vida do projeto, e as temporárias, que nascem para uma tarefa e são removidas após o merge.
Branches permanentes:
main— contém o código que está em produção. Cada commit nessa branch representa uma versão lançada.develop— o ponto de integração contínua. Todas as funcionalidades concluídas chegam aqui antes de ir para produção.
Branches temporárias:
feature/*— para desenvolver novas funcionalidadesrelease/*— para preparar uma nova versão para produçãohotfix/*— para corrigir bugs críticos diretamente em produção
Instalando o Git Flow
A maioria das distribuições Linux oferece o git-flow como pacote:
sudo apt install git-flow # Debian/Ubuntu
Inicializando em um repositório existente:
git flow init
O comando faz algumas perguntas sobre os nomes das branches — aceitar os padrões é a escolha correta na maioria dos casos.
Fluxo de uma Nova Funcionalidade
# Inicia uma feature branch a partir da develop
git flow feature start configurar-monitoramento
# O Git cria e já muda para a branch feature/configurar-monitoramento
# Trabalha-se normalmente com commits
echo "# Prometheus Config" > prometheus.yml
git add prometheus.yml
git commit -m "feat: adiciona configuração base do Prometheus"
# Quando a funcionalidade está pronta, finaliza-se
git flow feature finish configurar-monitoramento
O feature finish faz o merge de volta para develop, remove a branch de feature e volta para develop. Tudo em um único comando.
Preparando uma Release
Quando a develop tem um conjunto de funcionalidades prontas para ir a produção, cria-se uma branch de release:
# Inicia a release com o número de versão
git flow release start 1.2.0
Nessa branch, fazem-se apenas ajustes finais: atualização de número de versão, correções menores, atualização de changelog. Nenhuma funcionalidade nova entra aqui.
# Atualiza o arquivo de versão
echo "1.2.0" > VERSION
git add VERSION
git commit -m "chore: bump version to 1.2.0"
# Finaliza a release
git flow release finish 1.2.0
O release finish faz três coisas automaticamente:
- Merge na
main(marcando o código de produção) - Cria uma tag
1.2.0namain - Merge de volta na
develop(para que as correções feitas na release não se percam)
Corrigindo Bugs em Produção com Hotfix
Imagine que um bug crítico foi descoberto em produção. Não é possível esperar o ciclo normal de desenvolvimento — a correção precisa ir direto para a main:
# Inicia o hotfix a partir da main
git flow hotfix start 1.2.1
# Corrige o bug
git add .
git commit -m "fix: corrige falha de autenticação em requests concorrentes"
# Finaliza
git flow hotfix finish 1.2.1
O hotfix finish faz merge tanto na main quanto na develop, garantindo que a correção também esteja presente no código em desenvolvimento.
Git Flow sem o Plugin
É perfeitamente possível seguir o modelo Git Flow sem o plugin, usando apenas os comandos nativos do Git. O plugin é um atalho — entender o que acontece por baixo é mais importante:
# Equivalente ao git flow feature start minha-feature
git checkout develop
git checkout -b feature/minha-feature
# Equivalente ao git flow feature finish minha-feature
git checkout develop
git merge --no-ff feature/minha-feature
git branch -d feature/minha-feature
O flag --no-ff (no fast-forward) força a criação de um merge commit mesmo quando o fast-forward seria possível. Isso preserva no histórico a evidência de que aquele conjunto de commits veio de uma feature branch — informação valiosa ao auditar o histórico.
Quando Usar Git Flow — e Quando Não Usar
O Git Flow brilha em projetos com ciclos de release definidos — aplicações com versões numeradas, bibliotecas, produtos com janelas de lançamento planejadas.
Ele é excessivo para equipes que fazem deploy contínuo — onde cada commit na branch principal pode ir a produção a qualquer momento. Nesses casos, modelos mais simples como o GitHub Flow (apenas main e feature branches) ou Trunk-Based Development (todos trabalham diretamente na main com feature flags) são mais adequados.
A escolha do modelo depende do ritmo de entregas da equipe e da maturidade do pipeline de CI/CD — assunto que será aprofundado no Módulo 4.
O Que Vem a Seguir
No próximo artigo será abordado o GitHub Actions — a ferramenta que transforma eventos no repositório em automações: testes que rodam a cada push, deploys que acontecem a cada merge na main, notificações automáticas. É onde Git e DevOps se conectam de forma concreta pela primeira vez.
Referências para Aprofundamento
Artigo original e evolução
- A Successful Git Branching Model — Vincent Driessen — O artigo original de 2010 que introduziu o Git Flow. O próprio autor adicionou uma nota em 2020 discutindo quando o modelo é e não é adequado.
- GitHub Flow — GitHub Docs — A alternativa mais simples ao Git Flow, usada pelo próprio GitHub. Boa leitura para entender os trade-offs entre os modelos.
Leitura complementar
- Trunk Based Development — Site dedicado ao modelo de desenvolvimento baseado em trunk, com argumentos técnicos sobre escalabilidade e integração contínua.
- Pro Git — Capítulo 3: Branching — Capítulo em português do Pro Git cobrindo o modelo interno de branches e merge do Git.
Prática
- Learn Git Branching — Os níveis avançados do simulador cobrem merges complexos e rebase, que complementam o entendimento do Git Flow.
Exercícios
Exercício 1
Qual o papel da main e qual o da develop? Que pergunta essa separação permite responder que uma branch só não responderia?
Ver resposta
✓ Resposta: A main guarda o código que está em produção — cada commit nela representa uma versão lançada. A develop é o ponto de integração contínua: toda funcionalidade concluída chega ali antes de ir a produção. A pergunta que a separação responde é "o que exatamente está no ar agora?", e a resposta passa a ser um lugar único e confiável. Com uma branch só, código pronto e código publicado convivem misturados, e descobrir o que já foi entregue vira arqueologia de histórico.
Exercício 2
O git flow release finish 1.2.0 executa três operações. Quais são elas, e por que o merge de volta na develop é indispensável?
Ver resposta
✓ Resposta: Ele faz merge na main, cria a tag 1.2.0 nesse ponto e faz merge de volta na develop. O terceiro passo é indispensável porque a branch de release não é só uma passagem: nela foram feitos o bump de versão, o changelog e as correções de última hora. Sem o retorno à develop, esses commits morrem junto com a branch — e o bug corrigido às pressas durante a release reaparece intacto na versão seguinte, porque o desenvolvimento continuou de um ponto que nunca soube da correção.
Exercício 3
Por que um hotfix nasce a partir da main, e não da develop?
Ver resposta
✓ Resposta: Porque a develop contém funcionalidades que ainda não foram lançadas. Um hotfix que partisse dela levaria, no merge para a main, código não testado nem aprovado para produção — ou seja, resolveria um bug crítico introduzindo novidades inéditas no mesmo movimento, exatamente o oposto do que se quer sob pressão. Partindo da main, a correção contém precisamente o que está no ar mais o conserto, e nada além. E o hotfix finish faz merge nas duas branches, para que a correção não desapareça no próximo ciclo de desenvolvimento.
Exercício 4
O que a flag --no-ff faz, e por que o Git Flow a utiliza ao finalizar uma feature?
Ver resposta
✓ Resposta: Ela força a criação de um merge commit mesmo quando o fast-forward seria possível. Sem ela, a feature se dissolve no histórico: seus commits entram na develop indistinguíveis de commits feitos diretamente ali, e a informação de que aquilo era uma unidade de trabalho desaparece. Com --no-ff, o histórico preserva o agrupamento — dá para ver onde a feature começou e terminou, e desfazer o conjunto inteiro com um único git revert -m 1 em vez de caçar commit por commit.
Exercício 5
Em que situação o Git Flow é excessivo? Quais alternativas existem, e o que determina a escolha entre elas?
Ver resposta
✓ Resposta: Ele é excessivo em equipes que praticam deploy contínuo, onde cada commit na branch principal pode ir a produção a qualquer momento. Nesse ritmo, a develop e as branches de release/* viram etapas de espera que atrasam a entrega sem reduzir risco. As alternativas são o GitHub Flow — apenas main e feature branches — e o Trunk-Based Development, em que todos trabalham na main e o que ainda não deve aparecer fica atrás de feature flags. O que determina a escolha é o ritmo de entrega somado à maturidade do pipeline: quanto mais automatizado e confiável o CI/CD, menos camadas de branch são necessárias para dar segurança.
Exercício 6
Traduza os dois comandos do plugin para Git puro. Por que vale conhecer o equivalente nativo?
git flow feature start minha-feature
git flow feature finish minha-feature
Ver resposta
✓ Resposta: O start equivale a git checkout develop seguido de git checkout -b feature/minha-feature. O finish equivale a git checkout develop, git merge --no-ff feature/minha-feature e git branch -d feature/minha-feature. Vale conhecer o equivalente por dois motivos práticos: o plugin não está instalado em todo lugar — servidor de CI, container enxuto, máquina de um colega — e, quando algo falha no meio de um finish, só quem conhece as etapas nativas consegue identificar em qual delas parou e retomar dali, em vez de rodar o comando de novo e piorar o estado.