Branching

Branch e head
  • Branching é a duplicação de um branch
    • Depois do branching, cada branch pode ser modificado separadamente em paralelo
  • O branching implica na capacidade de posteriormente mergear ou integrar as mudanças
  • Poderá haver algum esforço para resolver conflitos de merge:
    • Conflito textual × conflito semântico
    • Principais fatores que influenciam o esforço na resolução de conflitos:
      • Complexidade das linhas de código em conflito
      • Modularidade: acoplamento × coesão
      • Tamanho dos branches: número de linhas de código modificadas ou adicionadas depois do branching
    • Via de regra, quando dobramos o tamanho dos branches:
      • O valor esperado e a incerteza do esforço na resolução de conflitos quadruplica
Branching e merge

Vantagens e Desvantagens de Branching

Vantagens

  • Permite que partes do software sejam desenvolvidas em paralelo
  • Permite que os desenvolvedores isolem as mudanças numa base de código estável
  • Facilita a manter várias versões em produção

Desvantagens

  • Menor interação entre os membros do time
  • Branchear é fácil, mergear é difícil
  • Não há como criar um algoritmo para resolver conflitos automaticamente
  • Muitos times gastam uma quantidade excessiva de tempo lidando com seu emaranhado de branches
Falha apontada por LeRoy em como as pessoas desenham os diagramas de branches

Git-flow

Criado por Vincent Driessen em 2010.

Modelo de Git-flow

Branch Principal ou Tronco

  • No Git-flow, o branch principal é chamado develop

Feature Branching

  • Um branch separado para cada feature
  • Tem origem no develop
  • Pode ter qualquer nome que não comece com release ou hotfix
  • O escopo do branch deve ser definido precisamente na sua criação
    • Nunca realizar tarefas fora do escopo pré-definido na branch
  • Quando houver novos commits no develop:
    • Mergeie o develop para o branch do feature
  • Quando terminar o feature:
    • Integrar com o develop
Branch de feature

Branches de Release

  • Branches de release são cortados de um commit específico no develop
  • Convenção de nomenclatura release-v<n>.<m>
  • Não permite que novos features sejam adicionados ao release
  • Os desenvolvedores que trabalham no release se concentram exclusivamente em remover quaisquer defeitos que impeçam o release de estar pronto para produção
  • Se não há mais falhas para lidar:
    • O branch está pronto para release em produção
  • Essas correções devem ser mergeadas ao develop
  • Conforme mais commits modificam o branch principal:
    • Fica cada vez mais difícil mergear o branch de release no branch principal
  • É muito comum negligenciar a integração das correções
Branch de release
  • Algumas pessoas preferem a criação dessas correções no develop, (como Google)
  • Quando estiverem funcionando:
    • Cherry-pická-los no branch de release
  • Desvantagens:
    • Muitos times acham difícil fazer isso
    • Pode ser necessário retrabalhar as correções no branch de release
Aplicar correções no branch principal
  • Os branches de release são necessários para projetos em que existem várias versões em produção
Branches de release com múltiplas versões em produção

Branches de Hotfix

  • Branch para capturar trabalho para corrigir um defeito de produção urgente
  • Abrir o branch na última versão de release
  • Quando o hotfix for concluído:
    • O hotfix deve ser mergeado ao develop
  • Se houver um branch de release aberto para a próxima versão:
    • O hotfix precisará ir para lá também
Branch de hotfix
  • O trabalho de hotfix pode ser feito no branch de release
  • É possível fazer os hotfixes no branch principal, cherry-pická-los para o branch de release
Hotfix em um branch de release

Branch de Produção

  • Branch que rastreia as versões entregues para produção
  • Para preparar um release para produção:
    • Abrir um branch de release para estabilizar o produto
    • Quando estiver pronta: copiá-lo para um branch de produção de longa duração
  • No Git-flow, o branch de produção é chamado de master
  • Uma alternativa ao uso de branch de produção é aplicar um esquema de tagueamento
Branch de produção

Vantagens e Desvantagens de Git-flow

Vantagens

  • O histórico de commits do repositório mostra um registro detalhado do que realmente aconteceu
  • É adequado para projetos em que existem várias versões em produção

Desvantagens

  • O histórico de Git se torna ilegível, cheia de uma série confusa de commits de merge
  • O branch de produção é desnecessário
  • Com 5 tipos de branches, o Git-flow é desnecessariamente complicado
  • Não adequado para Delivery Contínuo
    • Permite branches de feature de longa duração
    • Branch principal não pronto para o realease

OneFlow

Proposta no artigo Git-flow considered harmful por Adam Ruka em 2015.

Modelo de OneFlow
  • OneFlow chama seu branch principal de master
  • O branch de produção é substituído por um esquema de tagueamento
  • Todos os outros branches (feature, release, hotfix) são temporários, usados apenas como uma conveniência para compartilhar código com outros desenvolvedores e como uma medida de backup
  • Os features são integrados diretamente (rebase) no master, de forma a manter um histórico linear
  • Os releases e hotfixes são feitos de forma semelhante ao Git-flow

Vantagens e Desvantagens de Oneflow

Vantagens

  • O histórico do Git será mais limpo, menos confuso, mais legível
  • O histórico de commits mostra a história de como o projeto foi feito
  • O histórico do Git é passado a limpo
  • É adequado para projetos em que existem várias versões em produção

Desvantagens

  • Alguns times têm dificuldade de usar comandos para rescrita do histórico
  • Não adequado para o Delivery Contínuo
    • Permite branches de feature de longa duração
    • Branch principal não pronto para o release

GitHub Flow

Criado por Scott Chacon em 2011.

  • GitHub flow chama o branch principal de master
  • Única versão em produção
  • Branch principal pronto para release
  • Branches de releases não são necessários
  • Problemas de produção são corrigidos da mesma maneira que features regulares, assim não há necessidade de branches de hotfix
  • Feature branching de duração limitada
  • Revisão pré-integração usando Pull-Request

Branch Principal Pronto para Release

  • Manter o branch master suficientemente saudável para que o head do master possa sempre ser colocado diretamente em produção
  • Para manter o branch saldável é essencial escrever código de autoteste:
    • Conjunto abrangente de testes automatizados, para que possamos ter confiança de que, se esses testes passarem, o código de produção não conterá bugs
    • Executados rapidamente, geralmente não mais do que dez minutos
    • Toma mais tempo do que o desenvolvimento do código de produção
  • Precisamos manter qualidade interna do código alta usando práticas como:
    • Análise de programa estática
    • Revisão pré-integração
  • Se o time usa feature branching de longa duração (> 2 semanas):
    • O branch principal pronto para o release pode ser uma barreira para sua melhoria
  • Vantagens:
Branch principal pronto para release

Feature Branching de Duração Limitada

  • No GitHub flow, os branches de feature são pushados regularmente para o repositório origin
  • Não há integração com o masteraté o feature seja concluído
  • O GitHub flow recomenda branches de feature de duração limitada entre dez minutos a duas semanas incluindo a revisão pré-integração
  • O estudo do Relatório State Of DevOps indicou que as equipes de desenvolvimento de elite integram com mais frequência do que as de baixo desempenho
    • Aumenta a frequência de merges, mas reduz sua complexidade e risco
    • Alerta as equipes sobre conflitos com muito mais rapidez
    • Aumenta a interação entre os membros do time

Revisão Pré-integração no Modo de Pull Request

  • O modelo Pull Request (PR) foi introduzido pelo GitHub, em 2008
  • Google pratica modelo semelhante desde 2005
  • Todo o código é revisado antes de ser integrado
  • O tempo da revisão deve ser aproximadamente metade do tempo de desenvolvimento do código sendo integrado
  • Alguns desenvolvedores squasham (rebase) as mudanças em um único commit antes de iniciar um pull request
Josh pede ajuda para Brian
Brian responde com alguns conselhos
Josh reconhece os comentários de Brian
Pusha mais códigos para os atender

Desenvolvimento Baseado no Tronco

Paul Hammand escreveu um site detalhado para explicar essa abordagem.

  • O Desenvolvimento Baseado no Tronco se concentra em fazer todo trabalho no branch principal (chamado de “tronco”), evitando assim qualquer tipo de branch de longa duração
  • Integração contínua
  • Times podem usar:
    • Branch de release (“branch para release”)
    • Branch principal pronto para release (“release a partir do tronco”)
  • Google pratica Desenvolvimento Baseado no Tronco:
    • 2+ bilhões de linhas de código
    • Tronco monorepo único
    • Checkout esparso
Desenvolvimento baseado no Tronco para times menores
Desenvolvimento Baseado no Tronco para times maiores

Integração Contínua

  • Integração contínua:
    • Nunca deve ter mais de um dia de trabalho não integrado no repositório local de ninguém
    • Toda integração é buildada e testada com código de autoteste
  • Não é necessário de que o feature esteja completo
  • O time deve conhecer técnicas para ocultar features parciais como:
    • Branch por abstração para mudanças mais longas
    • Feature flags no desenvolvimento do dia a dia
  • Pode integrar diretamente no master ou usar branches de feature de curta duração

Confusão com Ferramentas de CI

  • Uma ferramenta de CI é um serviço que builda automaticamente o produto de software antes de cada delivery (como Jenkins, Team City, Travis CI, Circle CI, Bamboo)
  • As organizações que usam essas ferramentas as usa para buildar automaticamente branches de feature de duração maior que um dia não estão praticando integração contínua
  • Um melhor nome para essas ferramentas seria ferramentas de Build Contínuo

Feature Branching × Integração Contínua

Conforme Martin Fowler:

Feature Branching Integração Contínua
❌ Merges menos frequentes
✔ Todo o código em um feature pode ser avaliado quanto à qualidade como uma unidade
✔ O código do feature só é adicionado ao produto quando o feature estiver completo
✔ Merges menores
✔ Tempo reduzido para encontrar conflitos
✔ Encoraja a refatoração
✔ Apoia integração em período menor do que o tamanho do feature
❌ Requer compromisso com branches saudáveis (e, portanto, código de autoteste)
Evidência científica de que contribui para um maior desempenho de entrega de software

Recomendações

  • Sempre que estiver pensando em usar um branch, procure entender as consequências no merge
  • Certifique-se de entender as alternativas ao Git-flow, como o GitHub flow e o Desenvolvimento Baseado no Tronco, que são geralmente superiores
  • Pratique revisão pré-integração com duração de aproximadamente metade do tempo de desenvolvimento do código
  • Tente duplicar sua frequência de integração
  • Quando a duração dos branches de feature não for maior do que 1 semana:
    • Pratique o branch principal pronto para o release