O que é tão difícil sobre as fusões SVN?

28

Possível duplicata:
Eu sou um nerd do Subversion, por que devo considerar ou não o Mercurial, o Git ou qualquer outro DVCS?

De vez em quando, você ouve alguém dizendo que o controle de versão distribuído (Git, HG) é inerentemente melhor que o controle de versão centralizado (como o SVN) porque a fusão é difícil e dolorosa no SVN. O problema é que nunca tive problemas com a fusão no SVN, e como você só ouve essa alegação de defensores do DVCS, e não de usuários reais do SVN, isso tende a me lembrar daqueles comerciais desagradáveis ​​na TV em que eles tente vender-lhe algo de que não precisa, fazendo com que atores desonestos finjam que o que você já tem e funciona bem é incrivelmente difícil de usar.

E o caso de uso invariavelmente levantado é a re-mesclagem de uma ramificação, o que me lembra novamente os anúncios de produtos de palha; se você sabe o que está fazendo, não deve (e nem precisa) re-mesclar uma ramificação em primeiro lugar. (É claro que é difícil fazer isso quando você está fazendo algo fundamentalmente errado e bobo!)

Portanto, descontando o caso de uso ridículo do strawman, o que há na mesclagem SVN inerentemente mais difícil do que a mesclagem em um sistema DVCS?

Mason Wheeler
fonte
6
Ainda estou para trabalhar em um ambiente em que eles têm meses de ramificação mesclados e usam controle de versão distribuído. Os únicos lugares em que trabalhei com ramificações de longa duração usaram o TFS / Subversion. Eu espero que essas ramificações de longa duração também sejam difíceis de mesclar com DVCSes.
Oded
13
@MasonWheeler Estou intrigado. Para que você usa um VCS? Vi e li que uma (das muitas) práticas recomendadas é ter ramificações de recursos. A fusão de volta ao tronco é obrigatória nesse caso. Ou eu entendi mal alguma coisa? (sim, as quebras metáfora da árvore, mas não foi tão útil para começar IMO)
Andres F.
9
@MasonWheeler: Eu acho que você está interpretando a analogia da árvore um pouco literalmente demais.
Whatsisname 26/10/12
8
@MasonWheeler De quantos ambientes diferentes de desenvolvimento você tem experiência, se nunca ouviu falar de uma fusão ao tronco? Algumas lojas têm tronco estável e ramificações experimentais; nesse caso, a escolha de peças bem-sucedidas de volta ao estábulo é um evento regular.
itsbruce

Respostas:

25

É porque o svn não possuía as estruturas de dados adequadas para determinar com precisão o último ancestral comum dos dois ramos. Isso não é muito importante para uma ramificação que é mesclada apenas uma vez, mas pode causar muitos conflitos de mesclagem incorretos em situações em que várias ramificações são mescladas várias vezes.

Eu não sigo o svn de muito perto, mas meu entendimento é que esses problemas técnicos específicos foram corrigidos nas versões recentes. No entanto, não foi corrigido cedo o suficiente para dissipar o mito, e as pessoas que tentaram o DVCS para as fusões o mantiveram por outros motivos.

Karl Bielefeldt
fonte
47

se você sabe o que está fazendo, não deve (e nem precisa) re-mesclar uma ramificação em primeiro lugar. (É claro que é difícil fazer isso quando você está fazendo algo fundamentalmente errado e bobo!)

E é aí que reside a fonte da sua confusão e de todo o problema em geral.

Você diz que a fusão de ramificações é "fundamentalmente errada e boba". Bem, esse é exatamente o problema: você está pensando em galhos como coisas que não devem ser mescladas. Por quê? Porque você é um usuário SVN que sabe que a fusão de ramificações é difícil . Portanto, você nunca faz isso e incentiva os outros a não fazê-lo. Você foi treinado para evitar a fusão; você desenvolveu técnicas que você usa para evitar a fusão.

Eu sou um usuário do Mercurial. Mesmo em meus próprios projetos, onde sou o único desenvolvedor, mesclo ramos o tempo todo . Eu tenho um ramo de lançamento, no qual eu corrigi. Bem, eu mesclo isso de volta à linha principal para que a correção vá até lá.

Se eu estivesse usando SVN, adotaria uma estrutura completamente diferente da base de código. Por quê? Como o SVN dificulta a mesclagem, você desenvolve expressões idiomáticas e técnicas para evitar a mesclagem complexa.

Os DVCS facilitam mesclagens complexas porque são o estado padrão . Tudo é um ramo, mais ou menos, em um DVCS. Portanto, toda a estrutura deles é construída desde o início para facilitar a fusão. Isso permite que você desenvolva um fluxo de trabalho que utiliza a mesclagem diariamente, em vez do fluxo de trabalho SVN em que você nunca usa a mesclagem.

O simples fato é o seguinte: você deve abordar um DVCS de uma maneira diferente da SVN. Você deve usar os idiomas apropriados para esses tipos muito diferentes de sistemas de controle de versão. No SVN, você adota idiomas que não envolvem mesclagem porque as mesclas são difíceis. Nos DVCS, você adota idiomas que frequentemente usam mesclagens porque não são um grande problema.

Ferramenta certa para o trabalho certo.

O problema é que o fluxo de trabalho com foco em mesclagem é muito mais agradável e fácil de usar do que o fluxo de trabalho no estilo SVN, no qual você não mescla coisas. É mais fácil ver quando algo do ramo de lançamento foi trazido para o ramo de desenvolvimento. É mais fácil ver as várias interações entre os ramos. É fácil criar ramificações de teste para as coisas e cortá-las se o teste não funcionar. E assim por diante.

Realmente, Joel explica isso muito melhor do que eu . Você deve ter uma boa leitura disso.

Nicol Bolas
fonte
15
@Mason: Como isso não está treinando? Você foi treinado para usar o SVN no estilo SVN. E o estilo SVN é não usar a mesclagem. Assim, você foi treinado para não usar ou mesmo considerar a fusão de coisas. Por isso nunca lhe ocorreu; porque você usou um sistema que dificulta.
Nicol Bolas
5
Há uma grande diferença entre "não treinado para" e "treinado para não".
Mason Wheeler
8
@MasonWheeler: Não, não há. Se você não for ensinado adequadamente a fazer algo, será implicitamente treinado para não fazê-lo. Não está no seu repertório de expressões idiomáticas que você pode empregar para resolver um problema. Portanto, você não pode usá-lo para resolver problemas. O efeito não é diferente de ser dito para não mesclar, porque mesmo se você quisesse, você não sabe como. A maneira como você descarta de imediato um bom argumento como "o mesmo velho e cansado terreno" é evidência disso. Você não pensa em mesclar como uma ferramenta; você pensa nisso como uma exceção ou algo incomum. Algo a ser questionado em vez de usado.
Nicol Bolas
9
@MasonWheeler: Quem é você para decidir " eles estão fazendo errado "? Você não usa DVCSs, portanto, não tem experiência com o fluxo de trabalho do DVCS. Você não tem idéia se é útil para os programadores ou não, pois você não tem experiência com isso. Então, que autoridade você tem para dizer que está "errado" só porque o SVN não permite? É como dizer que classes, funções virtuais e modelos estão errados porque C não os possui.
Nicol Bolas
3
@MasonWheeler: assim? : P . A ramificação e fusão do SVN fazem a mesma coisa - a metáfora já está quebrada. Eu realmente não vejo como algo como isso é tão difícil de entender, especialmente se ele inclui alguns sensata comprometer comentários ..
naught101
21

Não há nada muito difícil sobre a fusão SVN ... mais ... se você seguir a filosofia certa

O que vejo na maioria das outras respostas parece vir de pessoas que não usam SVN há algum tempo. Como alguém menciona com precisão: "não foi corrigido cedo o suficiente para dissipar o mito".

Da minha experiência atual de usar o SVN 1.6 a 1.8 em um projeto herdado recentemente, o SVN foi um longo caminho para tornar a fusão uma coisa muito mais fácil. No entanto, não é infalível e acho que não sofre com que os usuários se desviem facilmente do uso pretendido.

Embora eu conhecesse o SVN muito bem e também tentasse o Mercurial para projetos pessoais nesse meio tempo, nunca havia feito muitas ramificações no SVN antes desse projeto. Houve várias tentativas e erros e tive muitos conflitos inesperados de mesclagem quando iniciei.

Por fim, porém, percebi que toda vez que recebia um (ou algum outro problema), era porque não havia feito as coisas corretamente (também conhecido como "o caminho do SVN" - sem dúvida, o caminho do controle de versão). Acredito que é aqui que está a dificuldade: você não pode fazer o que quiser de maneira desorganizada e espera que o SVN funcione perfeitamente, especialmente com mesclagens. As mesclagens exigem disciplina rigorosa do (s) usuário (s) antes de mostrar seu verdadeiro poder.

Aqui estão algumas coisas que eu notei que são recomendações fortes, se não requisitos, para um uso limpo de mesclagens:

  • Use uma versão recente do SVN (1.6 e superior na minha opinião). Mais e mais automações e verificações são feitas para você.
  • Use a estrutura padrão "trunk, branches, tags" e aplique sua filosofia (não se comprometa com tags). O SVN não verifica nada para você. Se você usar uma tag como uma ramificação (esse é o estado em que encontrei o repositório do projeto), ela ainda funcionará, mas você precisará ser consistente.
  • Saiba o que são ramificações e quando criá-las. Mesmo com tags.
  • Mantenha as ramificações laterais atualizadas com sua ramificação de origem (geralmente tronco, mas você pode ramificar-se de qualquer ramificação tecnicamente). Isso é obrigatório se você deseja que o SVN faça fusões automáticas. O SVN 1.8 realmente impede a mesclagem automática se as coisas não estiverem atualizadas e também se houver modificações pendentes na sua cópia de trabalho (esse comportamento parece ter desaparecido novamente no 1.8.5).
  • Faça confirmações "apropriadas". Eles devem conter apenas modificações em um conceito muito específico. Tanto quanto possível, eles devem conter uma pequena quantidade de alteração. Você não deseja que uma única confirmação contenha modificações sobre dois erros independentes, por exemplo. Se você já corrigiu os dois e eles estão no mesmo arquivo, você deve armazenar as alterações de um bug para poder confirmar apenas as alterações do outro primeiro e depois confirmar o segundo conjunto de alterações. Note que o TortoiseSVN permite isso facilmente através de "Restaurar após confirmação".
    • Fazer isso torna possível reverter um conjunto independente de alterações independente E torna possível mesclar apenas esse conjunto em outra ramificação. Sim, o SVN permite mesclar revisões escolhidas pela cereja.
  • Se você usar sub-ramificações (ramificação do tronco e ramificação da nova ramificação), respeite a hierarquia. Se você atualizar o sub-ramo com o tronco ou vice-versa, terá algumas dores. As mesclagens devem ser colocadas em cascata na hierarquia.
    • Após alguns meses de experiências, posso garantir que essa pode ser a parte mais importante. Tentei criar duas sub-ramificações do mesmo tronco e depois mesclar bits entre as sub-ramificações, ou algumas vezes entre as sub-ramificações de ambos os lados. Isso pode ativar o SVN (ou o usuário). Pode funcionar bem se você estiver mesclando revisões específicas. A mesclagem automática pode ter problemas com isso.
    • Eu tive problemas especificamente ao sincronizar a sub-ramificação A com o tronco e tentar mesclar algo da sub-ramificação A no sub-ramo B. O SVN parece pensar que a revisão "sincronizar do tronco" deve legitimamente ser mesclada no sub-ramo B e isso leva a uma massa de conflitos.
  • Na medida do possível, mesclar a partir da raiz do ramo. Caso contrário, SVN só vai acompanhar as fusões feito para a sub-pasta e quando você fazer tentativa de auto-merge a partir da raiz, você pode obter alguns avisos sobre a falta de revisões não mescladas. É corrigível simplesmente mesclando-os da raiz, mas é melhor evitar a confusão.
  • Tenha cuidado com qual ramo você se compromete. Se você usar o Switch para que sua cópia de trabalho aponte para várias ramificações ao longo do tempo, verifique onde você está se comprometendo.
    • É especialmente ruim se você realmente não queria a mudança nesse ramo. Ainda não estou claro sobre isso, mas dependendo de como você se livra dele / o transfere para o ramo certo (revertendo, mesclando), você pode obter algo confuso. É corrigível, mas você terá que mesclar revisão por revisão para evitar ou resolver imediatamente possíveis conflitos, ou precisará corrigir um conflito possivelmente mais complexo após a mesclagem automática.
  • Não mantenha os galhos intocados por muito tempo. Na verdade, não é uma questão de tempo, mas de quantas revisões foram comprometidas no ramo e no tronco e quanto mudou nessas. Mesclagens entre duas ramificações, mesclas de três vias, sempre são comparadas à revisão comum mais recente entre as ramificações. Quanto mais alterações ocorrerem, mais alterações ocorrerão na mesclagem automática. Obviamente, isso é muito pior se você alterar a estrutura do seu código nesse meio tempo (arquivos movidos ou renomeados).

Se você não seguir o acima, é bem provável que tenha conflitos. Eles são sempre solucionáveis, mas não muito divertidos para passar o tempo.

Ah, mais uma coisa sobre mesclar onde, de tudo o que li e tentei, o SVN realmente é péssimo: arquivos / pastas excluídos / movidos / renomeados. Aparentemente , o SVN ainda não pode lidar com um arquivo que está sendo renomeado, excluído ou movido em um ramo, e sua versão original modificada em outro ramo ... e depois mesclando-os. Ele simplesmente não saberá para onde o arquivo foi de uma maneira e "esquecerá" as alterações da outra maneira. Uma mudança é obviamente insolúvel (você exclui ou altera o arquivo, não pode fazer as duas coisas), mas a aplicação de alterações nos arquivos movidos / renomeados deve funcionar e não funciona. Espero que isso seja corrigido em breve.

Então, apesar de tudo, a fusão do SVN é fácil? Eu acho que não. Não de uma maneira despreocupada, com certeza. Isso é ruim ? Acho que não. Ele só aparece na sua cara quando você a usa da maneira errada e não pensa o suficiente no que está fazendo.

Com base nisso, posso ver por que as pessoas podem preferir o Mercurial (por exemplo), pois é um pouco mais branda sobre essas coisas da minha experiência e tinha tudo automatizado desde o início (pelo menos nas versões anteriores). No entanto, o SVN alcançou um pouco, então não vale mais tanto esforço.

leokhorn
fonte
Conflitos em árvores - sim, o SVN tem dificuldade com eles, embora o TBH o faça com todos os outros SCM. O Git tem algumas heurísticas para tentar descobrir se os arquivos que foram renomeados ou movidos são os mesmos, mas não (não pode!) Sempre acerta. Eu acho que o SVN deve se esforçar para facilitar a resolução desses conflitos.
Gbjbaanb
@gbjbaanb: Oferece "Repair Move" como o Mercurial, embora não ofereça heurísticas. Você precisa dizer quais arquivos excluídos e adicionados são, de fato, os mesmos. Definitivamente espaço para melhorias.
Leokhorn
Tudo isso soa bem quando você é a única pessoa trabalhando no projeto ... Mas se você tem uma equipe de bom tamanho e todos estão usando o "caminho SVN" (que ninguém parece concordar exatamente com o que é), mescla ainda são uma PITA. O fato é que o svn não suporta muito bem o fluxo de trabalho de ramificação. A "maneira SVN" seria nem mesmo criar ramificações e usar um SDLC em cascata. Tudo isso dito, tive problemas com o Git mesclado no passado em grandes projetos com várias pessoas trabalhando nele. Mas, eles pareciam ainda ser muito menos dolorosos.
ryoung
Minha experiência é que, se você estiver trabalhando com pessoas que não se importam com o funcionamento do sistema de controle de versão, o SVN é muito mais fácil de usar no dia a dia. Eu trabalhei apenas em algumas equipes do DVCS, mas invariavelmente um número substancial da equipe não possui um bom comportamento de controle de revisão e polui o repositório para todos. No Subversion, os não treinados geralmente ficam longe das filiais, para que os "especialistas" façam isso por eles e sejam gerenciados adequadamente. É verdade que essa experiência é só minha e eu preferiria trabalhar apenas com programadores que sabiam como suas ferramentas funcionavam ...
dash-tom-bang
5

Os modelos de dados internos são fundamentalmente diferentes.

Fundamentalmente, no SVN, quando você olha para o histórico de uma ramificação, vê apenas o que aconteceu nessa ramificação. Portanto, quando você mesclar de ramificação Bem ramificação A, o histórico da ramificação Aconterá uma confirmação grande contendo todas as alterações feitas explicitamente Bdesde que foram ramificadas.

Nas primeiras versões do SVN, se você tiver que mesclar ramificação Bem ramificação Amais uma vez, precisará especificar manualmente qual intervalo de revisão de ramificação Bdeseja mesclar para evitar mesclar as mesmas revisões duas vezes. É claro que o desenvolvedor inteligente usaria uma mensagem de confirmação como 'Mesclado em B: 1234'.

O SVN 1.5 "corrigiu" isso. Mas não mudou como as fusões são aplicadas fundamentalmente. Apenas adicionou alguns metadados extras à ramificação A, informando ao SVN que a revisão 1234 foi mesclada, permitindo que o SVN escolha automaticamente o intervalo de revisão correto.

Mas essa solução é basicamente uma solução alternativa para um modelo de dados que fundamentalmente não suporta o rastreamento do que foi mesclado.

Mesclar duas ramificações é um exemplo relativamente simples. Mas imaginar esse cenário mais complexo

  1. Crie uma ramificação Ade trunke faça algumas confirmações aqui
  2. Criar ramo Bde Ae fazer alguns commits aqui
  3. Faça algumas confirmações trunkeA
  4. Mesclar Bemtrunk
  5. Mesclar AemB
  6. Mesclar Aemtrunk
  7. Mesclar Bem trunk(isso realmente não deve fazer nada)

Manipular isso corretamente usando o modelo de metadados se torna extremamente complexo (não sei se o SVN realmente manipula esse cenário corretamente e não me sinto inclinado a testá-lo).

Lidar com esse cenário no git é extremamente simples.

No git, toda vez que você confirma, o objeto interno que representa essa confirmação contém uma referência ao cabeçalho anterior. Quando você mescla um ramo, o commit contém referências ao cabeçalho anterior de todos os ramos que estão sendo mesclados (você pode mesclar mais de um ramo por vez no git)

Portanto, quando você examina o histórico de um único commit no git, pode ver todo o histórico, quando foi ramificado, quando foi mesclado e o histórico dos dois ramos entre a ramificação e a mesclagem.

Portanto, ao mesclar em uma ramificação parcialmente mesclada, é extremamente simples determinar o que já foi mesclado e o que não foi.

Não tenho experiência com Mercurial, mas suspeito que seu funcionamento interno seja semelhante ao git.

Então, fundamentalmente, para o SVN, era um objetivo do projeto tornar as ramificações baratas. Mas no git, era um objetivo do projeto tornar a fusão barata.

Por fim, da última vez que usei o SVN, ele não foi capaz de lidar com mesclagens, onde um arquivo foi renomeado em uma ramificação e modificado em outra.

Pete
fonte
1

Fiz várias combinações de SVN - incluindo ter ramificações de desenvolvimento e lançamento de longa duração. De um modo geral, eu sobrevivi. A fusão é sempre complicada, mas com o DCVS a desvantagem não é terrivelmente ruim - tudo é local, basta atualizar para uma boa revisão conhecida e continuar. Enquanto o SVN aconteceu muito no servidor, a recuperação foi feia - geralmente envolvia a remoção da cópia local e o check-out de uma nova ramificação limpa para tentar novamente. Não foi ruim no meu caso - uma conexão de gigabit com a caixa SVN ajuda. Mas tivemos alguns contratados que tiveram muitos problemas com isso, pois estavam em conexões lentas, então tudo levou uma eternidade, incluindo fusões.

Wyatt Barnett
fonte
extrapolando a conexão lenta, trabalhar em um servidor remoto externo também gera erros de conexão muito ruins ao fazer grandes atualizações> <Não é nada divertido.
jxramos
-1

Sim, eu também faço isso. Atualmente, tenho 12 VMs para diferentes versões (ramificações) do projeto do qual faço parte no trabalho. Quando tenho que corrigir um bug em uma versão mais antiga, eu o corrigo e, em seguida, mesclo esse commit nas ramificações para versões mais recentes. Mas isso agora está reorganizando um ramo inteiro, e é disso que estou falando aqui.

Aqui está uma das coisas mais legais do git. Não é herdado do DVCS, é apenas algo que o git se destaca. Você pode mesclar revisões específicas de qualquer ramificação em outra ramificação. Basicamente, apenas pega o diff e o aplica ao outro ramo, mas faz o rastreamento e é muito mais automático.

Portanto, se você possui a ramificação 2.0 e a ramificação 3.0 e descobre um bug na 2.0, pode corrigi-lo na 2.0 e pegar o conjunto de revisões que a resolvem e mesclar apenas essas revisões na ramificação 3.0. Não acredito que o SVN tenha outra maneira de fazer isso, a não ser pegar manualmente as diferenças para cada revisão e aplicá-las

Obviamente, o algoritmo de mesclagem automática também parece funcionar muito mais suavemente, e o git foi construído a partir do zero no modelo "faça uma ramificação para todas as coisas", de modo que a ramificação é realmente suave e fácil. Parece natural ramificar-se frequentemente com a leveza dos galhos

Earlz
fonte
Além disso, eu imagino que mercurial tem funcionalidade semelhante
Earlz
2
Na verdade, você pode fazer exatamente a mesma coisa no SVN. Eu faço isso o tempo todo. O comando SVN Merge pode obter uma revisão (ou intervalo de revisões) de uma ramificação diferente e aplicá-la à sua cópia de trabalho e, em seguida, você a confirma.
Mason Wheeler
2
@MasonWheeler Lembre-se de que grande parte do sentimento anti-svn foi direcionado para versões anteriores à 1.5 (quando o svn obteve rastreamento de mesclagem). E, claro, um monte de que é apenas fanboys inútil ...
Yannis
3
@MasonWheeler veja também stackoverflow.com/a/4215199/69742 Essa postagem se resume ao DVCS mantém o controle dos conjuntos de alterações e não das versões . Mudança-conjuntos são inerentemente fáceis de tomar e mesclar ... versões não tanto porque eles exigem contexto
Earlz
@MasonWheeler oh e este: stackoverflow.com/questions/2471606/…
Earlz 26/12