Pelo meu entendimento, o SVN é 'Fácil de ramificar. Difícil de mesclar '. Por que é que? Existe alguma diferença em como eles se fundem?
Pelo meu entendimento, o SVN é 'Fácil de ramificar. Difícil de mesclar '. Por que é que? Existe alguma diferença em como eles se fundem?
Respostas:
Por favor, veja minha resposta do Stack Overflow para uma situação muito concreta em que o Mercurial (e o Git) se funde sem problemas e o Subversion apresenta um conflito falso. A situação é uma refatoração simples feita em uma ramificação na qual você renomeia alguns arquivos.
No que diz respeito à resposta do tdammers, há uma série de mal-entendidos:
Subversion, Mercurial e Git, todos controlam instantâneos do projeto em todo o repositório. Chamá-los de versões , revisões ou conjuntos de alterações não faz diferença. Todos são instantâneos logicamente atômicos de um conjunto de arquivos.
O tamanho de suas confirmações não faz diferença quando se trata de mesclagem. Todos os três sistemas se fundem com o algoritmo de mesclagem padrão de três vias e as entradas para esse algoritmo são
Não importa como as duas versões de ramificação foram criadas. Você pode ter usado 1000 confirmações pequenas desde a versão ancestral ou 1 confirmação. Tudo o que importa é a versão final dos arquivos. (Sim, isso é surpreendente! Sim, muitos guias do DVCS entendem isso terrivelmente errado.)
Ele também levanta alguns bons pontos sobre as diferenças:
O Subversion possui algum "vodu", de onde você pode mesclar /trunk
, digamos /branches/foo
,. Mercurial e Git não usam esse modelo - os ramos são modelados diretamente na história. Portanto, a história se torna um gráfico acíclico direcionado em vez de linear. Este é um modelo muito mais simples que o usado pelo Subversion e corta vários casos de canto.
Você pode atrasar facilmente uma mesclagem ou até deixar que outra pessoa lide com ela. Se houver hg merge
muitos conflitos, você poderá pedir a seu colega de trabalho hg pull
e ele terá exatamente o mesmo estado. Então ele pode hg merge
e talvez ele seja melhor em resolver conflitos do que você.
Isso é muito difícil no Subversion, onde você precisa atualizar antes de poder confirmar. Você não pode simplesmente ignorar as alterações no servidor e continuar se comprometendo em sua própria ramificação anônima. Em geral, o Subversion força você a brincar com uma cópia de trabalho suja quando você svn update
. Isso é meio arriscado, pois você não armazenou suas alterações em nenhum lugar seguro. Git e Mercurial permitem que você confirme primeiro e depois atualize e mescle conforme necessário.
A verdadeira razão pela qual Git e Mercurial são melhores na fusão do que o Subversion é uma questão de implementação. Existem conflitos de renomeação que o Subversion simplesmente não consegue lidar, mesmo que seja claro qual é a resposta correta. Mercurial e Git lida com esses facilmente. Mas não há razão para o Subversion não lidar com isso também - estar centralizado certamente não é o motivo.
trunk
no SVN. Com um DVCS, você pode confirmar sem compartilhar, mas no SVN você svn commit
afetará diretamente outras pessoas que trabalham no mesmo ramo. Mesmo que nós dois trabalhemos em uma filial no SVN, não posso confirmar meu trabalho sem ter que me fundir imediatamente com o seu trabalho. Isso torna os commits um pouco assustadores - o que é uma propriedade assustadora para um sistema de controle de versão! :-)
O principal problema está na maneira como esses sistemas representam uma estrutura de diretório com versão.
O conceito básico do Subversion em torno do qual todo o sistema gira é o de uma versão (ou, no svn lingo, "revisão"): uma captura instantânea de um arquivo em um determinado ponto. Desde que a história seja perfeitamente linear, tudo está bem, mas se você precisar mesclar alterações de duas linhas independentes de desenvolvimento, o svn precisará comparar as versões atuais de ambas e, em seguida, fazer uma comparação de três maneiras entre a última versão compartilhada e as duas versões principais. As linhas que aparecem alteradas em uma das cabeças, mas não na outra, podem ser facilmente resolvidas; linhas que se desviam exatamente da mesma maneira em ambas as cabeças são mais difíceis, mas geralmente são possíveis; linhas que se desviam de maneiras diferentes são o que faz o svn dizer "Não consigo entender isso, humano, por favor, resolva isso para mim."
Por outro lado, git e mercurial controlam os conjuntos de alterações em vez das versões. O repositório inteiro é uma árvore de conjuntos de alterações, cada um dependendo de um pai, onde um conjunto de alterações pai pode ter qualquer número de filhos e a raiz da árvore representa um diretório vazio. Em outras palavras, git / hg diz "primeiro eu não tinha nada, então esse patch foi aplicado, depois esse patch, etc.". Quando você precisa mesclar duas linhas de desenvolvimento, o git / hg não apenas sabe como são as cabeças atualmente e como era a última versão comum, mas também como a transição aconteceu, permitindo uma fusão muito mais inteligente.
Outra coisa que facilita a fusão em um DVCS é uma conseqüência indireta da separação dos conceitos de confirmação e envioe de permitir todos os tipos de mesclagens cruzadas entre dois clones do mesmo repositório a qualquer momento. Com o svn, as pessoas tendem a confirmar grandes conjuntos de alterações com alterações frequentemente não relacionadas, porque um commit também é uma atualização no repositório central que afeta todos os outros membros da equipe; se você cometer uma versão corrompida, todo mundo ficará bravo com você. Como a maioria das configurações envolve um servidor svn em rede, a confirmação também envolve o bombeamento de dados pela rede, o que significa que a confirmação introduz um atraso considerável no fluxo de trabalho (especialmente quando sua cópia de trabalho está desatualizada e você precisa puxar primeiro). Com o git e o mercurial, o commit ocorre localmente e, como ambos são muito eficientes no manuseio de sistemas de arquivos locais, geralmente termina instantaneamente. Como resultado, as pessoas (quando se acostumam) cometem pequenas alterações incrementais e, quando funciona, empurre uma dúzia ou mais comete de uma só vez. Então, quando chegar a hora da mesclagem, o SCM terá informações muito mais detalhadas e poderá executar um trabalho melhor na solução de conflitos de forma segura e automática.
E há os detalhes agradáveis que tornam as coisas ainda mais fáceis:
hg mv
ou hg addremove --similarity...
), enquanto o Git usa heurística, mas ambas tratam de renomeação . Posso ter conflito de árvore mesmo com uma diferença de 1 string nos arquivos mesclados! Você precisa reaprender alguns aspectos do Subversion, desculpe.
rename a b
como copy a b; remove a
e ambos fazem isso em uma confirmação atômica. A diferença no comportamento de mesclagem decorre da manipulação diferente de casos de canto e do Subversion, permitindo mais mesclagens que Mercurial e Git. Finalmente, o Git detecta renomeação na mesclagem e no tempo de log - estamos pensando em adicionar isso no Mercurial também.