Estratégia de ramificação Git para código não lançado de longa duração

15

Em nossa equipe, além de unidades de trabalho individuais (Histórias), temos temas de trabalho de duração mais longa (Epics). Várias histórias são épicas.

Tradicionalmente, tínhamos ramificações de recursos para cada história e as fundíamos diretamente para serem dominadas quando elas passavam no controle de qualidade. No entanto, gostaríamos de adiar o lançamento de histórias concluídas em uma epopeia até que a epopéia seja considerada "recurso concluído". Só lançaríamos esses recursos para produção quando toda a Epic estivesse fechada. Além disso, temos um servidor de construção noturno - gostaríamos que todas as histórias fechadas (incluindo aquelas que fazem parte de épicas incompletas) fossem implantadas automaticamente nesse servidor noturno.

Existem sugestões sobre como gerenciar nosso repositório para conseguir isso? Eu considerei a introdução de "ramificações épicas", onde combinaríamos histórias fechadas com a ramificação épica relacionada em vez de direta para dominar, mas minhas preocupações são:

  • Preocupo-me com os conflitos de mesclagem que podem surgir se ramificações épicas forem mantidas abertas por muito tempo
  • As construções noturnas exigiriam a fusão de todas as ramificações épicas em uma ramificação "construção noturna". Novamente, conflitos de mesclagem podem surgir, e isso deve ser feito automaticamente
Sitati
fonte

Respostas:

23

Sugestão simples: não faça isso.

As ramificações git não são para garfos de código demorado, como discutido aqui e https://blog.newrelic.com/2012/11/14/long-running-branches-considered-harmful/ . As ramificações são melhor tratadas como coisas transitórias usadas para organizar confirmações por um desenvolvedor individual no nível do dia-a-dia. Portanto, se eles tiverem um nome que corresponda a algo que um gerente de projeto (sem falar no usuário final) possa se preocupar com o fato de você estar fazendo algo errado.

A prática recomendada é usar a integração contínua com alternância de recursos ou ramificação por abstração para garantir que:

  • todo o código é integrado o tempo todo (pelo menos todos os dias, de preferência com mais frequência)
  • o que é implantado está sob controle explícito.
soru
fonte
1
Eu suspeitava que essa poderia ser uma resposta popular! Minhas principais preocupações com isso são a sobrecarga de manter sempre a implementação 'ao vivo' e a 'próxima', e também exige que o desenvolvedor que trabalha em um recurso saiba antecipadamente criar alterações como novos recursos paralelos em vez de atualizar (/ substituir) o funcionalidade existente. Acho que isso exige uma mudança maior de mentalidade na equipe.
Sitati
Não há problema em usar ramificações para desenvolver código, nunca use-as para armazenar código. Portanto, se você não tiver certeza se uma tarefa é uma correção de 30 minutos ou um retrabalho de 2 semanas, inicie em uma ramificação. Assim que você souber, mesclar ou refatorar para uma abstração / alternar e mesclar.
soru
@ Sitati: Acabei de mesclar algum código que estava em um ramo de recursos nos últimos quatro meses. Enquanto develisso, mudamos o Autotools para CMake, introduzimos o Travis CI e refatoramos o código. No final, foi mais fácil entender o novo recurso e aplicá-lo manualmente do develque tentar mesclá-lo. Também tivemos novos alunos de mestrado desenvolvendo um novo recurso em um ramo que eles ramificaram quando começaram sua tese. Depois de um ano, eles pressionaram e não houve nenhum esforço para incorporá-lo de volta, por isso ficou mais difícil mesclar dia após dia.
Martin Ueding
2
A postagem do blog vinculado agora tem 5 anos. Eu odeio alternar recursos. O que há de errado em ramificar a longo prazo, mesclar regularmente de novo no ramo de recursos e adicionar integração contínua ao ramo de recursos de longo prazo?
Jason Kelley
CI é o nome de um processo, não uma ferramenta. Se você tiver mais de uma ramificação de recursos, elas normalmente não serão continuamente integradas entre si. O que significa encontrar problemas mais tarde do que antes.
soru 11/08/19
1

Eu acho que esse é um problema bastante comum e se resume a escolher quais recursos incluir em um release depois que os recursos foram codificados e não antes.

por exemplo.

Eu tenho os recursos A, B e C da v2 do meu produto. B e C estão relacionados, não quero liberar B, a menos que C também esteja concluído.

Eu tenho três desenvolvedores trabalhando ao mesmo tempo nos recursos.

Eu tenho um conjunto na data de lançamento de pedra D

B está terminado e fundido, A está terminado e fundido. C está atrasado ... o que eu faço ?!

Não acredito que haja uma solução técnica para esse problema. Você deseja liberar uma versão não testada do produto com apenas o recurso A incluído. A menos que você mescle e teste todas as combinações possíveis de recursos, isso sempre será uma possibilidade.

A solução é mais humana. Você perdeu sua data de lançamento e deve devolvê-la.

Ewan
fonte
1

Este é um problema complicado, mas que muitas pessoas enfrentam. Prefiro usar a configuração do Gitflow como ponto de partida.

Desenvolvimento -> Novos itens sendo trabalhados no
Master -> Novos itens que precisam ser testados Produção -> Novos itens publicados na produção.

Em recursos menores (mais curtos), crio uma ramificação a partir do desenvolvimento, faça o trabalho lá e, em seguida, mesclamos a ramificação de volta ao desenvolvimento.

Nos principais recursos (a longo prazo), crio uma ramificação a partir do desenvolvimento, crio ramificações menores a partir dessa ramificação e, em seguida, volto à primeira ramificação. Depois que o recurso principal estiver concluído, volte ao ramo de desenvolvimento.

A intervalos regulares (depende do projeto), mesclo o desenvolvimento novamente ao mestre e um ciclo de testes começa. Se alguma correção surgir no teste, ela será feita na ramificação principal (sub ramificação e mesclada). E o desenvolvimento pode continuar na ramificação principal durante o teste.

A qualquer momento, o mestre deve ser mesclado ao desenvolvimento, e o desenvolvimento deve ser mesclado a qualquer um de seus sub-ramos de longo prazo.

o mestre deve sempre (em teoria) estar pronto para a produção. O desenvolvimento deve sempre (em teoria) estar pronto para a produção. A única razão pela qual existe uma diferença é fornecer um conjunto sólido de recursos para os testadores testarem.

Quando pronto, uma consolidação no mestre que é testada é mesclada à produção e a implantação na produção acontece a partir dessa ramificação. Os HOTFIXs que precisam ser executados em uma emergência podem ocorrer no ramo Produção sem ter que mesclar no mestre (que pode ter muitas alterações não testadas).

Minha árvore normal parece

 LongTerm -> Development -> Master -> Production    
 LongTerm <- Development      |            |  
     |       Development -> Master         |  
 LongTerm <- Development -> Master         |  
             Development <- Master         |  
                            Master -> Production  

É minha regra geral que nenhuma mudança isolada demore mais do que algumas horas. Se isso acontecer, ele precisará ser transformado em alterações menores. Se é um recurso imenso (como uma reescrita da interface do usuário), isso ocorre a longo prazo, para que o desenvolvimento normal possa continuar ao mesmo tempo. As ramificações LongTerm normalmente são apenas ramificações locais, enquanto Desenvolvimento, Mestre e Produção são ramificações remotas. Quaisquer sub-ramificações também são apenas locais. Isso mantém o repositório limpo para outras pessoas, sem perder a utilidade do git em um conjunto de recursos de longo prazo.

Gostaria de observar, no entanto, que a existência de um ramo de longo prazo é algo raro. Normalmente, todo o meu trabalho está em desenvolvimento. Somente quando tenho um recurso (conjunto) que levará tanto tempo que também preciso trabalhar em coisas normais de desenvolvimento, devo usar o ramo LongTerm. Se é apenas um conjunto de mudanças que devem estar juntas, simplesmente não me fundo até que tudo esteja pronto.

coteyr
fonte
"Nos principais recursos (de longo prazo), crio uma ramificação do desenvolvimento" - você não deve criar novas ramificações de recursos (desenvolvimento) a partir da ramificação Produção? Ver como ramo de produção é um código pronto para lançamento.
robotron
Não, a produção já está liberada, o mestre está à frente da produção e o desenvolvimento está à frente do mestre. Um novo recurso, como adicionar imposto aos totais dos pedidos, não faz sentido se você não estiver trabalhando no código que já possui pedidos.
coteyr
Mas se você ramificar do dev e posteriormente se unir novamente, esse ramo (e consequentemente mestre e produção posteriormente) incorporará todas as alterações de desenvolvimento feitas por outras pessoas até o ponto de ramificação? Algumas dessas alterações podem não ter aprovação de controle de qualidade. Talvez estivéssemos falando sobre diferentes abordagens para liberar o gerenciamento.
robotron
Sim, é esse o ponto. Testes de controle de qualidade em um SHA específico no mestre, mas você não pode manter o desenvolvedor por isso.
coteyr
"O controle de qualidade testa um SHA específico no mestre" -> o controle de qualidade testa cada novo recurso como autônomo? Deixe-me apresentar a você um cenário típico que minha equipe enfrenta: digamos que você tenha 2 projetos de longa execução na mesma base de código: O Projeto A está em controle de qualidade do mês passado e será submetido a controle de qualidade por mais um mês. O Projeto B estava em desenvolvimento nos últimos 6 meses e agora está pronto para o controle de qualidade. O Projeto A é mesclado no mestre e definitivamente não está pronto para produção devido a vários erros sutis de regra de negócios. Como lidamos com o Projeto B? A e B precisam ser testados juntos para verificar se há interações (B não causará conflitos durante a mesclagem).
robotron