Por que a ramificação e a fusão são mais fáceis no Mercurial do que no Subversion?

92

Lidar com fusões múltiplas em branches no Subversion ou CVS é ​​apenas uma daquelas coisas que deve ser experimentado. É muito mais fácil controlar os branches e merges no Mercurial (e provavelmente em qualquer outro sistema distribuído), mas não sei por quê. Alguém mais sabe?

Minha dúvida vem do fato de que com o Mercurial você pode adotar uma prática de trabalho semelhante à do repositório central do Subversions / CVS e tudo funcionará bem. Você pode fazer várias mesclagens no mesmo branch e não precisará de pedaços de papel intermináveis ​​com números de confirmação e nomes de tag.

Eu sei que a última versão do Subversion tem a capacidade de rastrear mesclagens para ramos para que você não tenha o mesmo grau de incômodo, mas foi um grande e importante desenvolvimento da parte deles e ainda não faz tudo que a equipe de desenvolvimento faria gosto de fazer.

Deve haver uma diferença fundamental na maneira como tudo funciona.

Nick Pierpoint
fonte

Respostas:

115

No Subversion (e CVS), o repositório está em primeiro lugar. Em git e mercurial não existe realmente o conceito de repositório da mesma maneira; aqui as mudanças são o tema central.

+1

O incômodo no CVS / SVN vem do fato de que esses sistemas não lembram a paternidade das mudanças. No Git e no Mercurial, não apenas um commit pode ter vários filhos, mas também pode ter vários pais!

Isso pode ser facilmente observado usando uma das ferramentas gráficas, gitkou hg view. No exemplo a seguir, o branch nº 2 foi bifurcado do nº 1 no commit A, e desde então foi mesclado uma vez (em M, mesclado com o commit B):

o---A---o---B---o---C         (branch #1)
     \       \
      o---o---M---X---?       (branch #2)

Observe como A e B têm dois filhos, enquanto M tem dois pais . Esses relacionamentos são registrados no repositório. Digamos que o mantenedor do branch # 2 agora deseja mesclar as mudanças mais recentes do branch # 1, ele pode emitir um comando como:

$ git merge branch-1

e a ferramenta saberá automaticamente que a base é B - porque ela foi gravada no commit M, um ancestral da ponta de # 2 - e que ela deve mesclar o que quer que tenha acontecido entre B e C. O CVS não registra esta informação , nem o SVN antes da versão 1.5. Nesses sistemas, o gráfico seria semelhante a:

o---A---o---B---o---C         (branch #1)
     \    
      o---o---M---X---?       (branch #2)

onde M é apenas um commit gigantesco "esmagado" de tudo o que aconteceu entre A e B, aplicado em cima de M. Observe que depois que a ação é realizada, não há nenhum vestígio deixado (exceto potencialmente em comentários legíveis por humanos) de onde M originou de, nem de quantos commits foram colapsados ​​juntos - tornando a história muito mais impenetrável.

Pior ainda, realizar uma segunda fusão torna-se um pesadelo: é preciso descobrir qual era a base de fusão no momento da primeira fusão (e é preciso saber que houve uma fusão em primeiro lugar!) E, em seguida, apresentar isso informações para a ferramenta para que ela não tente reproduzir A..B em cima de M. Tudo isso é difícil o suficiente quando se trabalha em estreita colaboração, mas é simplesmente impossível em um ambiente distribuído.

Um problema (relacionado) é que não há como responder à pergunta: "X contém B?" onde B é uma correção de bug potencialmente importante. Então, por que não registrar essa informação no commit, já que é conhecida na hora do merge!

P.-S. - Não tenho experiência com as habilidades de gravação de mesclagem do SVN 1.5+, mas o fluxo de trabalho parece ser muito mais elaborado do que nos sistemas distribuídos. Se esse for realmente o caso, provavelmente é porque - conforme mencionado no comentário acima - o foco é colocado na organização do repositório ao invés das próprias mudanças.

Damien Diederen
fonte
6
O SVN 1.5+ realmente colocaria uma propriedade SVN no commit de mesclagem M listando os commits mesclados que ele contém, em outras palavras AB. Então você tem as mesmas informações.
Simon D
Mais ou menos. Tecnicamente, o rastreamento de mesclagem do SVN é semelhante ao que o Git chama de “seleção seletiva”, com magia adicional para torná-lo mais fácil para o usuário; é semanticamente diferente do que Git, Hg e Bzr fazem ao mesclar. Eu acho que não faz muita diferença na prática, desde que você não se importe com o DAG ( eagain.net/articles/git-for-computer-scientists ).
Damien Diederen,
2
Ai de que não haja um botão +100. Obrigado.
Charlie Flowers
Presumo que o recurso SVN 1.5 de que você está falando seja o uso da svn:mergeinfopropriedade.
MatrixFrog
@MatrixFrog: Sim, é exatamente svn:mergeinfoisso que faz.
sleske,
12

Porque o Subversion (pelo menos a versão 1.4 e abaixo) não controla o que foi mesclado. Para o Subversion, mesclar é basicamente o mesmo que qualquer commit, enquanto em outro controle de versão como Git, o que foi mesclado é lembrado.

Htanata
fonte
7

Sem ser tocado por nenhuma das respostas já fornecidas, o Hg ofereceu recursos de mesclagem superiores porque usa mais informações ao mesclar as alterações ( hginit.com ):

Por exemplo, se eu mudar uma função um pouco e depois movê-la para outro lugar, o Subversion realmente não se lembra dessas etapas, então quando chega a hora de fundir, pode pensar que uma nova função apareceu do nada . Considerando que o Mercurial se lembrará dessas coisas separadamente: função alterada, função movida, o que significa que se você também alterou essa função um pouco, é muito mais provável que o Mercurial mesclará com sucesso nossas alterações.

Claro, lembrar o que foi mesclado pela última vez (o ponto abordado pela maioria das respostas fornecidas aqui) também é uma grande vitória.

Ambas as melhorias, entretanto, são questionáveis, já que o subversion 1.5+ armazena informações adicionais de fusão na forma de propriedades do subversion: essas informações disponíveis, não há razão óbvia para que o subversion merge não pudesse implementar a fusão com tanto sucesso quanto Hg ou Git. Eu não sei se isso acontece, mas certamente parece que os desenvolvedores do subversion estão a caminho de contornar esse problema.

Tomislav Nakic-Alfirevic
fonte
4

Suponho que isso possa ser parcialmente devido ao Subversion ter a ideia de um servidor central junto com uma linha de tempo absoluta de revisões. O Mercurial é verdadeiramente distribuído e não faz referência a uma linha de tempo absoluta. Isso permite que os projetos do Mercurial formem hierarquias mais complicadas de branches para adicionar recursos e ciclos de teste por subprojeto, no entanto, as equipes agora precisam manter muito mais ativamente o controle das fusões para se manterem atualizados, pois não podem simplesmente clicar em atualizar e terminar com isso .

Mal Andy
fonte
3

No Subversion (e CVS), o repositório está em primeiro lugar. Em git e mercurial não existe realmente o conceito de repositório da mesma maneira; aqui as mudanças são o tema central.

Eu não pensei muito sobre como você implementaria qualquer um, mas minha impressão (com base na experiência amarga e muita leitura) é que essa diferença é o que torna a fusão e ramificação muito mais fácil em sistemas não baseados em repositório.

Stephen Darlington
fonte
1

Eu só tenho experiência com o Subversion, mas posso dizer que a tela de mesclagem no TortoiseSVN é terrivelmente complicada. Felizmente, eles incluem um botão de simulação para que você possa ver se está fazendo certo. A complicação está na configuração do que você deseja mesclar e onde. Depois de configurar a mesclagem, a mesclagem geralmente funciona bem. Então você precisa resolver todo e qualquer conflito e então enviar sua cópia de trabalho mesclada para o repositório.

Se o Mercurial pode tornar a configuração da fusão mais fácil, então posso dizer que isso tornaria a fusão 100% mais fácil do que o Subversion.

RedWolves
fonte