Estratégias para mesclar 1 ano de desenvolvimento no Visual Studio

32

Eu tenho um cliente que insistiu em manter nosso novo desenvolvimento separado das principais filiais durante todo o ano de 2016. Eles tinham 3-4 outras equipes trabalhando no aplicativo em várias capacidades. Várias grandes alterações foram feitas (alternando como a injeção de dependência é feita, limpando o código com o ReSharper, etc.). Agora cabe a mim mesclar o principal em nosso novo ramo de desenvolvimento para me preparar para impulsionar nossas mudanças na cadeia.

No meu pull de mesclagem inicial, o TFS relatou ~ 6500 arquivos com resolução de conflitos. Alguns deles serão fáceis, mas outros serão muito mais difíceis (especificamente alguns javascript, controladores de API e serviços que suportam esses controladores).

Existe uma abordagem que eu possa adotar que facilitará isso para mim?

Para esclarecer, expressei muita preocupação com essa abordagem várias vezes ao longo do caminho. O cliente estava e está ciente das dificuldades com isso. Como eles escolheram reduzir a equipe de controle de qualidade (1 testador para 4 desenvolvedores, nenhum teste automatizado, pouco teste de regressão), eles insistiram em manter nosso ramo isolado das mudanças no ramo principal sob o pretexto de que isso reduziria a necessidade de nosso testador para saber sobre as alterações sendo feitas em outros lugares.

Um dos maiores problemas aqui é a atualização para a versão angular e alguns dos outros softwares de terceiros - infelizmente não temos uma boa maneira de criar essa solução até que todas as peças sejam colocadas novamente no lugar.

user258451
fonte
63
Não. Você tem dois ramos separados que foram desenvolvidos ativamente por um ano. A mesclagem será péssima.
17 de 26
2
Qual é a extensão das mudanças que sua equipe fez? Pode ser mais eficiente identificar essas alterações e reaplicá-las manualmente na atual base de código principal.
precisa saber é o seguinte
2
É a totalidade de 2015 ou 2016? Se for 2015, é de 2 anos, o que significa que será uma merda dupla.
David diz Reinstate Monica
1
Por que o cliente se importa se o trabalho que você está fazendo por eles está em uma ramificação separada no seu sistema de controle de versão?
Ixrec 4/17/17
17
Faça o que fizer, verifique se você está cobrando a cada hora.
Sean McSomething

Respostas:

37

Teria havido uma maneira simples de manter seu novo desenvolvimento separado do ramo principal sem levar você a esta situação infeliz: qualquer alteração do tronco deveria ser mesclada no seu ramo de desenvolvimento diariamente . (Seu cliente foi realmente tão míope que ele não podia prever que sua filial precisaria ser remetida de volta à linha principal algum dia?)

Enfim, a melhor abordagem é IMHO tentando refazer o que deveria ter acontecido em primeira mão:

  • identifique a semântica das alterações na linha principal do dia 1 após a criação da ramificação. Aplique-os à sua base de código atual da melhor maneira possível. Se foi uma "mudança local", deveria ser simples, se era uma "refatoração transversal", como renomear uma classe amplamente usada, aplique-a de uma maneira semanticamente equivalente à sua base de código atual. Felizmente, durante esse ano, não foram feitas alterações contraditórias na base de código na ramificação "your", caso contrário, isso pode se tornar um verdadeiro quebra-cabeças
  • teste o resultado (mencionei que você precisa de um bom conjunto de testes para esta tarefa)? Corrija todos os erros revelados pelo teste
  • agora repita esse processo para as alterações na linha principal do dia 2, depois do dia 3 e assim por diante.

Isso pode funcionar quando as equipes obedecem estritamente às regras clássicas de controle de versão ("apenas confirmam estados compiláveis ​​e testados" e "faz check-in antecipado e frequente").

Após 365 repetições (ou 250, se você tiver sorte e puder agrupar o trabalho para alterações no final de semana), estará quase concluído (quase, porque você precisará adicionar o número de alterações que ocorrerão na linha principal durante o período de integração) ) A etapa final será mesclar o ramo de desenvolvimento atualizado no tronco novamente (para que você não perca o histórico do tronco). Isso deve ser fácil, porque tecnicamente deve ser apenas uma substituição dos arquivos afetados.

E sim, estou falando sério, provavelmente não há atalho para isso. Pode ser que as "porções diárias" às vezes sejam muito pequenas, mas eu não esperaria isso, acho que é mais provável que as porções diárias possam ser muito grandes. Espero que seu cliente pague muito bem por isso, e que isso seja tão caro para ele que ele aprenderá com seu fracasso.

Devo acrescentar que você pode tentar isso também com os lados trocados - reintegrando as alterações do seu ramo em pequenas porções para a linha principal. Isso pode ser mais simples quando no seu ramo de desenvolvimento houve muito menos alterações do que no tronco, ou a maioria das alterações ocorreu em novos arquivos de origem que atualmente não fazem parte do tronco. Pode-se ver isso como "portando" um recurso de um produto A (o ramo dev) para um produto um pouco diferente B (estado atual do tronco). Mas se a maioria das refatorações transversais foram feitas na linha principal e afetam seu novo código (as colisões de mesclagem 6500 parecem ser uma evidência disso), talvez seja mais fácil a maneira como a descrevi primeiro.

Doc Brown
fonte
9
Se você continuar desenvolvendo o tronco durante a reintegração, sugiro que você ramifique a ponta do tronco primeiro e desenvolva a partir disso. Caso contrário, você estará fundindo efetivamente o passado e o futuro simultaneamente. Mas eu recomendo a Doc Brown qualquer descontinuidade no espaço-tempo, naturalmente.
Radarbob
1
@radarbob: o que você sugere faz sentido apenas se o OP se integrar do dev ao tronco, mas não quando ele decide se fundir do tronco ao dev, como descrevi primeiro. Se o OP transferir alterações do tronco para sua ramificação de desenvolvimento dia a dia (começando com alterações 365 dias no passado), não importará se o desenvolvimento no tronco continua. Ele apenas terá que continuar com essas táticas até chegar ao presente (presumindo que ele possa integrar e testar as mudanças dessas equipes de 3 a 4 em um dia em menos de um dia).
Doc Brown
Citação: "Devo acrescentar que você pode tentar isso também com os lados trocados - reintegrando as alterações do seu ramo em pacotes diários para a linha principal ". Sinto uma potencial cascata de "distorção de ressonância harmônica" com integrações de mudanças conflitantes.
Radarbob
Este é um bom conselho. Veja a edição para abordar algumas coisas aqui.
precisa saber é o seguinte
1
@ user258451: então você tinha equipes de controle de qualidade diferentes para o tronco e o novo ramo de desenvolvimento, que não queriam conversar? Grande Scott: - (((
Doc Brown
14

Naquele estágio de mesclagem, eu diria que a mesclagem automatizada pode apenas complicar demais o processo. Eu tive problemas semelhantes com filiais que divergiram por mais de um ano e o método mais eficaz que tenho é fazer o seguinte:

  • Faça uma cópia do estado original não imerso
  • Diferença entre o imerso e o mais recente
  • Divida todos os elementos comuns
    • Por exemplo, faça todas as alterações no nome da função, alterações nos parâmetros etc.
    • Ignore o espaço em branco no diff se os padrões forem alterados; caso contrário, você perderá muito tempo contando espaços
  • Concentre-se na funcionalidade principal primeiro

Eventualmente, os avisos do compilador e as diferenças serão seus melhores amigos, continue usando a diferença não imersa para ver exatamente o que era diferente e apenas continue. Pode haver várias ferramentas que você pode usar para ajudar, mas isso depende de você descobrir qual é o melhor.

A chave é continuar.

Editar:

Uma palavra de aviso, essa abordagem significa que o histórico de controle de versão ficaria "corrompido", pois você perderia as evidências da mesclagem de ramo a ramo, bem como o histórico do ramo não imerso.

Graças aos comentários de 'Jack Aidley' e '17 de 26 '

Erdrik Ironrose
fonte
1
O principal problema dessa abordagem é que ela destruirá o registro de alterações deixadas no sistema de controle de versão.
precisa saber é o seguinte
Essencialmente, fazendo todas as mesmas alterações uma segunda vez durante a mesclagem, você ainda teria um log das alterações, seria apenas na ordem feita na mesclagem em vez da ordem em que foram feitas durante o desenvolvimento. Não é o ideal, mas é melhor que nada. Além disso, você ainda teria o estado inalterado original, se isso fosse mantido no controle de versão.
Erdrik Ironrose
Você teria um log das alterações, mas não teria evidências históricas de que as alterações foram mescladas de ramificação em ramificação. Isso seria um grande negócio no TFS, que oferece apenas os conjuntos de alterações não imersos para escolher ao mesclar de ramificação em ramificação.
17 de 26
@ 17of26 Embora eu concorde que você possa restaurar alguns registros de alterações, 17 de 26 estão corretos, dizendo que esse registro não será completo ou preciso. Pode ser que essa abordagem seja suficientemente mais fácil para tornar essa perda de registro um comprometimento aceitável, dada a situação ruim em que estão agora. No entanto, acho que é uma desvantagem importante reconhecer, independentemente do que eles decidirem.
precisa saber é o seguinte
1
@ Jack Aidley Eu definitivamente concordo que é um problema, então eu adicionei um pouco à minha resposta para refletir. Espero que esteja tudo bem?
Erdrik Ironrose
8

Alguns anos atrás, tínhamos um cliente com os mesmos requisitos de manter filiais separadas. Então nós fizemos.

Nós nunca fundimos o ramo deles de volta. Eles tinham sua própria versão única. Cobramos mais por mudanças, pois basicamente tínhamos dois troncos principais em vez de um tronco e galhos principais.

Tentamos voltar ao tronco, mas após duas semanas decidimos abandonar esse esforço, pois estava queimando horas sem benefícios tangíveis.

Portanto, não mescle de volta. No futuro, mesclar correções críticas para essa filial do cliente, conforme necessário, e qualquer aprimoramento seria um custo cobrado especificamente para esse cliente.

Jon Raynor
fonte
Essa estratégia só é viável se as diferentes linhas de desenvolvimento atingirem clientes diferentes. Ou, se os casos de uso em que o produto estiver envolvido permitirem usar as duas linhas de produtos diferentes em paralelo, de maneira não integrada. No meu entender, o OP descreve uma situação em que a nova linha de desenvolvimento tem como alvo o mesmo cliente que está usando o tronco e não está claro se o uso paralelo de duas linhas de produtos pode fazer algum sentido para o seu caso.
Doc Brown
1

Não vai ser divertido, mas o quão doloroso será depende da natureza das mudanças e de quão isoladas elas são.

Sugiro que você tente convergir as ramificações através da refatoração, tanto quanto possível, antes de fazer uma mesclagem real.

A ferramenta de mesclagem é meio boba, porque apenas analisa diferenças de texto e não entende o código de forma alguma. Se a ramificação principal alterou o nome de uma classe usada em todo o aplicativo, e a ramificação de recurso usa o nome antigo em algum novo código, a ferramenta de mesclagem não entenderá que o nome da classe também deve ser alterado no novo código. Mas se você fizer uma refatoração na ramificação B para renomear a classe como na ramificação A, ela funcionará no código antigo e no novo e a mesclagem ocorrerá sem problemas.

Em segundo lugar, você deve inspecionar a localização das alterações no ramo de desenvolvimento. Se as alterações na ramificação do recurso estiverem localizadas em algumas áreas, você não precisará convergir o código não afetado, basta copiar e substituir a partir da ramificação principal.

Nas áreas de código em que houve alterações não triviais em ambas as ramificações, você deve inspecionar cuidadosamente o código e decidir como reescrever.

JacquesB
fonte