Costumo ler que Hg (e Git e ...) são melhores na fusão do que o SVN, mas nunca vi exemplos práticos de onde o Hg / Git pode mesclar algo em que o SVN falha (ou onde o SVN precisa de intervenção manual). Você poderia postar algumas listas passo a passo das operações de ramificação / modificação / confirmação /...- que mostram onde o SVN falharia enquanto o Hg / Git seguisse em frente? Casos práticos, não muito excepcionais, por favor ...
Alguns antecedentes: temos algumas dezenas de desenvolvedores trabalhando em projetos usando SVN, com cada projeto (ou grupo de projetos similares) em seu próprio repositório. Sabemos aplicar as ramificações de liberação e recurso para que não tenhamos problemas com muita frequência (ou seja, estivemos lá, mas aprendemos a superar os problemas de Joel de "um programador causando trauma a toda a equipe" ou "precisar de seis desenvolvedores por duas semanas para reintegrar uma filial"). Temos ramos de lançamento muito estáveis e usados apenas para aplicar correções. Temos troncos que devem ser estáveis o suficiente para poder criar uma liberação dentro de uma semana. E temos ramos de recursos nos quais desenvolvedores individuais ou grupos de desenvolvedores podem trabalhar. Sim, eles são excluídos após a reintegração para não desorganizar o repositório. ;)
Então, ainda estou tentando encontrar as vantagens do Hg / Git sobre o SVN. Eu adoraria ter alguma experiência prática, mas ainda não existem projetos maiores que pudéssemos mudar para o Hg / Git, por isso estou envolvido em brincar com pequenos projetos artificiais que contêm apenas alguns arquivos inventados. E estou procurando alguns casos em que você possa sentir o poder impressionante do Hg / Git, pois até agora eu sempre li sobre eles, mas não consegui encontrá-los.
Respostas:
Eu não uso o Subversion, mas a partir das notas de versão do Subversion 1.5: Rastreamento de mesclagem (fundamental) , parece que existem as seguintes diferenças de como o rastreamento de mesclagem funciona em sistemas de controle de versão completo do DAG , como Git ou Mercurial.
Mesclar tronco a ramo é diferente de mesclar ramo a tronco: por algum motivo, mesclar tronco a ramo exige a
--reintegrate
opçãosvn merge
.Nos sistemas de controle de versão distribuído, como Git ou Mercurial, não há diferença técnica entre tronco e ramificação: todas as ramificações são criadas da mesma forma ( embora possa haver diferença social ). A fusão em qualquer direção é feita da mesma maneira.
Você precisa fornecer uma nova opção
-g
(--use-merge-history
)svn log
esvn blame
levar em consideração o rastreamento de mesclagem.No Git e no Mercurial, o rastreamento de mesclagem é levado automaticamente em consideração ao exibir histórico (log) e culpa. No Git, você pode solicitar que siga o primeiro pai apenas com
--first-parent
(acho que existe uma opção semelhante também para o Mercurial) para "descartar" as informações de rastreamento de mesclagemgit log
.Pelo que entendi, a
svn:mergeinfo
propriedade armazena informações por caminho sobre conflitos (o Subversion é baseado em changeset), enquanto no Git e Mercurial é simplesmente confirmar objetos que podem ter mais de um pai.A subseção "Problemas conhecidos" para rastreamento de mesclagem no Subversion sugere que a mesclagem repetida / cíclica / refletiva pode não funcionar corretamente. Isso significa que, com os seguintes históricos, a segunda mesclagem pode não fazer a coisa certa ('A' pode ser tronco ou ramificação e 'B' pode ser ramificação ou tronco, respectivamente):
No caso de a arte ASCII acima ser interrompida: a ramificação 'B' é criada (bifurcada) a partir da ramificação 'A' na revisão 'x'; depois, a ramificação 'A' é mesclada na revisão 'y' na ramificação 'B' como mesclar 'M1' e, finalmente, a ramificação 'B' é mesclada na ramificação 'A' como mesclagem 'M2'.
Caso a arte ASCII acima seja interrompida: a ramificação 'B' é criada (bifurcada) a partir da ramificação 'A' na revisão 'x', é mesclada na ramificação 'A' em 'y' como 'M1' e, posteriormente, mesclado novamente na ramificação 'A' como 'M2'.
O Subversion pode não suportar casos avançados de mesclagem cruzada .
O Git lida com essa situação muito bem na prática, usando a estratégia de mesclagem "recursiva". Não tenho certeza sobre o Mercurial.
Em "Problemas conhecidos", há um aviso de que o rastreamento de mesclagem pode não funcionar com renomeação de arquivos, por exemplo, quando um lado renomeia o arquivo (e talvez o modifique), e o segundo lado modifica o arquivo sem renomear (sob o nome antigo).
Tanto o Git quanto o Mercurial lidam com esse caso muito bem na prática: Git usando detecção de renomeação , Mercurial usando rastreamento de renomeação .
HTH
fonte
<pre>...</pre>
bloco não é recuado como deve ser ...--reintegrate
está obsoleto.Eu também tenho procurado um caso em que, digamos, o Subversion não consiga mesclar um ramo e o Mercurial (e Git, Bazaar, ...) faça a coisa certa.
O SVN Book descreve como os arquivos renomeados são mesclados incorretamente . Isso se aplica ao Subversion 1.5 , 1.6 , 1.7 e 1.8 ! Tentei recriar a situação abaixo:
Segundo o livro, a mesclagem deve terminar de forma limpa, mas com dados incorretos no arquivo renomeado, pois a atualização
trunk
é esquecida. Em vez disso, recebo um conflito de árvore (isso é com o Subversion 1.6.17, a versão mais recente do Debian no momento da redação):Não deve haver nenhum conflito - a atualização deve ser mesclada com o novo nome do arquivo. Enquanto o Subversion falha, o Mercurial lida com isso corretamente:
Antes da mesclagem, o repositório fica assim (de
hg glog
):A saída da mesclagem é:
Em outras palavras: Mercurial pegou a alteração da revisão 1 e a fundiu com o novo nome de arquivo da revisão 2 (
hello.en.txt
). É claro que lidar com esse caso é essencial para oferecer suporte à refatoração e refatoração é exatamente o tipo de coisa que você deseja fazer em uma filial.fonte
Sem falar sobre as vantagens usuais (confirmações offline, processo de publicação , ...), aqui está um exemplo de "mesclagem" que eu gosto:
O cenário principal que eu continuo vendo é uma ramificação na qual ... duas tarefas não relacionadas são realmente desenvolvidas
(ele começou a partir de um recurso, mas levou ao desenvolvimento desse outro recurso.
Ou a partir de um patch, mas levou ao desenvolvimento de outro recurso).
Como você mescla apenas um dos dois recursos no ramo principal?
Ou como você isola os dois recursos em seus próprios ramos?
Você pode tentar gerar algum tipo de correção, o problema é que você não tem mais certeza das dependências funcionais que poderiam existir entre:
Git (e Mercurial também, suponho) propõe a opção rebase --onto para rebase (redefinir a raiz do ramo) parte de um ramo:
Da publicação de Jefromi
você pode desembaraçar esta situação em que possui patches para a v2, bem como um novo recurso wss em:
, permitindo que você:
O outro recurso que eu gosto (que influencia a mesclagem) é a capacidade de compactar confirmações (em uma ramificação ainda não enviada para outro repositório) para apresentar:
Isso garante fusões muito mais fáceis, com menos conflitos.
fonte
Recentemente, migramos do SVN para o GIT e enfrentamos essa mesma incerteza. Havia muitas evidências anedóticas de que o GIT era melhor, mas era difícil encontrar exemplos.
Posso dizer, porém, que o GIT é MUITO MELHOR na fusão do que o SVN. Isso é obviamente anedótico, mas há uma tabela a seguir.
Aqui estão algumas das coisas que encontramos:
Quando avaliamos o GIT, executamos os seguintes testes. Eles mostram o GIT como o vencedor quando se trata de fusão, mas não tanto assim. Na prática, a diferença é muito maior, mas acho que não conseguimos replicar as situações que o SVN lida mal.
fonte
Outros abordaram os aspectos mais teóricos disso. Talvez eu possa emprestar uma perspectiva mais prática.
Atualmente, estou trabalhando para uma empresa que usa SVN em um modelo de desenvolvimento "ramo de recursos". Isso é:
Em geral, funciona. O SVN pode ser usado para um fluxo como esse, mas não é perfeito. Existem alguns aspectos do SVN que atrapalham e moldam o comportamento humano. Isso dá alguns aspectos negativos.
^/trunk
. Essas ninhadas mesclam registros de informações por toda a árvore e, eventualmente, interrompem o rastreamento de mesclagem. Conflitos falsos começam a aparecer e a confusão reina.svn merge
faz o que você quer. Para mesclar suas alterações, é necessário que nos digam--reintegrate
o comando de mesclagem. Eu nunca entendi verdadeiramente essa opção, mas isso significa que o ramo não pode ser mesclado no tronco novamente. Isso significa que é um ramo morto e você precisa criar um novo para continuar trabalhando. (Veja a nota)O que costuma acontecer é que um engenheiro cria uma filial no dia 1. Ele inicia seu trabalho e esquece. Algum tempo depois, um chefe aparece e pergunta se ele pode liberar seu trabalho para o tronco. O engenheiro teme esse dia porque reintegrar significa:
... e como o engenheiro faz isso o mínimo possível, não consegue se lembrar do "encantamento mágico" para executar cada etapa. Mudanças e URLs incorretos acontecem e, de repente, eles estão confusos e vão buscar o "especialista".
Eventualmente, tudo se acalma, e as pessoas aprendem a lidar com as deficiências, mas cada novo iniciante passa pelos mesmos problemas. A realidade eventual (ao contrário do que expus no início) é:
...mas...
Felizmente, a equipe é pequena o suficiente para lidar, mas não seria escalável. O fato é que nada disso é um problema com o CVCS, mas mais do que isso, porque as mesclagens não são tão importantes quanto no DVCS, elas não são tão espertas. Esse "atrito de mesclagem" causa comportamento, o que significa que um modelo de "Filial de recursos" começa a quebrar. Boas fusões precisam ser um recurso de todos os VCS, não apenas do DVCS.
De acordo com isso , agora existe um
--record-only
comutador que pode ser usado para resolver o--reintegrate
problema e, aparentemente, a v1.8 escolhe quando fazer uma reintegração automática, e isso não causa a morte do ramo depoisfonte
Antes do subversion 1.5 (se não me engano), o subversion tinha uma desvantagem significativa, pois não se lembraria do histórico de mesclagem.
Vejamos o caso descrito por VonC:
Observe as revisões A e B. Digamos que você mesclou as alterações da revisão A na ramificação "wss" para a ramificação "somente v2" na revisão B (por qualquer motivo), mas continuou usando as duas ramificações. Se você tentasse mesclar os dois ramos novamente usando mercurial, ele só mesclaria as alterações após as revisões A e B. Com o subversion, você precisaria mesclar tudo, como se não tivesse feito uma mesclagem antes.
Este é um exemplo da minha própria experiência, em que a fusão de B para A demorou várias horas devido ao volume de código: isso teria sido uma dor real para passar novamente , o que seria o caso do subversion anterior à 1.5.
Outra diferença provavelmente mais relevante no comportamento de mesclagem do Hginit: Reeducação do Subversion :
Em suma, a maneira de Mercurial de analisar as diferenças é (foi?) Superior à da subversão.
fonte