D'après ma compréhension, SVN est «facile à créer. Difficile de fusionner ». Pourquoi donc? Y a-t-il une différence dans leur fusion?
D'après ma compréhension, SVN est «facile à créer. Difficile de fusionner ». Pourquoi donc? Y a-t-il une différence dans leur fusion?
Réponses:
Veuillez consulter ma réponse Stack Overflow pour une situation très concrète où Mercurial (et Git) fusionne sans problème et où Subversion vous présente un faux conflit. La situation est un simple refactoring effectué sur une branche où vous renommez certains fichiers.
En ce qui concerne la réponse des tdammers, il y a alors un certain nombre de malentendus:
Subversion, Mercurial et Git tous les instantanés du projet à l'échelle du référentiel. Les appeler versions , révisions ou ensembles de modifications ne fait aucune différence. Ce sont tous des instantanés logiquement atomiques d'un ensemble de fichiers.
La taille de vos validations ne fait aucune différence en matière de fusion. Les trois systèmes fusionnent avec l'algorithme de fusion à trois voies standard et les entrées de cet algorithme sont
Il n'a pas d' importance comment les deux versions de la branche ont été créées. Vous pouvez avoir utilisé 1000 petites validations depuis la version ancêtre, ou vous pouvez avoir utilisé 1 validation. Tout ce qui compte, c'est la version finale des fichiers. (Oui, c'est surprenant! Oui, beaucoup de guides DVCS se trompent horriblement.)
Il soulève également quelques bons points sur les différences:
Subversion a une certaine « voodoo » où vous pouvez fusionner à partir /trunk
en, disons, /branches/foo
. Mercurial et Git n'utilisent pas ce modèle - les branches sont plutôt modélisées directement dans l'historique. L'histoire devient donc un graphe acyclique dirigé au lieu d'être linéaire. C'est un modèle beaucoup plus simple que celui utilisé par Subversion et cela supprime un certain nombre de cas d'angle.
Vous pouvez facilement retarder une fusion ou même laisser quelqu'un d'autre s'en occuper. Si cela hg merge
vous donne une tonne de conflits, vous pouvez demander à votre collègue hg pull
de vous et ensuite il a exactement le même état. Il peut donc hg merge
et peut -être qu'il est mieux à même de résoudre les conflits que vous.
C'est très difficile avec Subversion où vous devez mettre à jour avant de pouvoir valider. Vous ne pouvez pas simplement ignorer les modifications sur le serveur et continuer à vous engager sur votre propre branche anonyme. En général, Subversion vous oblige à jouer avec une copie de travail sale lorsque vous svn update
. C'est un peu risqué car vous n'avez pas stocké vos modifications dans un endroit sûr. Git et Mercurial vous permettent de valider d'abord, puis de mettre à jour et de fusionner si nécessaire.
La vraie raison pour laquelle Git et Mercurial fusionnent mieux que Subversion est une question d'implémentation. Il existe des conflits de changement de nom que Subversion ne peut tout simplement pas gérer même si la réponse correcte est claire. Mercurial et Git les manipulent facilement. Mais il n'y a aucune raison pour que Subversion ne puisse pas gérer cela aussi - la centralisation n'est certainement pas la raison.
trunk
dans SVN. Avec un DVCS, vous pouvez vous engager sans partager, mais dans SVN, vous svn commit
affecterez directement ceux qui travaillent sur la même branche. Même si nous travaillons tous les deux sur une branche dans SVN, je ne peux pas engager mon travail sans avoir à fusionner immédiatement avec votre travail. Cela rend les commits quelque peu effrayants - ce qui est une propriété effrayante pour un système de contrôle de version! :-)
Le problème principal réside dans la façon dont ces systèmes représentent une structure de répertoires versionnée.
Le concept de base de Subversion autour duquel tourne tout le système est celui d'une version (ou, dans le jargon svn, "révision"): un instantané d'un fichier à un certain point. Tant que l'historique est parfaitement linéaire, tout va bien, mais si vous devez fusionner les modifications de deux lignes de développement indépendantes, svn doit comparer les versions actuelles des deux, puis faire une comparaison à trois entre la dernière version partagée et les deux versions de tête. Les lignes qui semblent modifiées dans l'une des têtes, mais pas dans l'autre, peuvent facilement être résolues; les lignes qui s'écartent exactement de la même manière dans les deux têtes sont plus dures, mais généralement réalisables; les lignes qui s'écartent de différentes manières sont ce qui fait dire à svn "Je ne peux pas comprendre ça, humain, s'il te plait résous ça pour moi."
En revanche, git et mercurial track changesets plutôt que des versions. Le référentiel entier est un arbre de changesets, chacun dépendant d'un parent, où un changeset parent peut avoir n'importe quel nombre d'enfants, et la racine de l'arbre représente un répertoire vide. En d'autres termes, git / hg dit "d'abord je n'avais rien, puis ce patch a été appliqué, puis ce patch, etc.". Lorsque vous devez fusionner deux lignes de développement, git / hg sait non seulement à quoi ressemble chaque tête actuellement, et à quoi ressemblait la dernière version commune, mais il sait également comment la transition s'est produite, permettant une fusion beaucoup plus intelligente.
Une autre chose qui facilite la fusion dans un DVCS est une conséquence indirecte de la séparation des concepts de commit et de push, et d'autoriser à tout moment toutes sortes de fusions croisées entre deux clones du même référentiel. Avec svn, les utilisateurs ont tendance à valider des ensembles de modifications volumineux avec des modifications souvent indépendantes, car une validation est également une mise à jour du référentiel central qui affecte tous les autres membres de l'équipe; si vous commettez une version cassée, tout le monde sera en colère contre vous. Étant donné que la plupart des configurations impliquent un serveur svn en réseau, la validation implique également le pompage de données sur le réseau, ce qui signifie que la validation introduit un retard considérable dans le flux de travail (en particulier lorsque votre copie de travail est obsolète et que vous devez d'abord tirer). Avec git et mercurial, la validation se produit localement, et parce que les deux sont très efficaces pour gérer les systèmes de fichiers locaux, elle se termine généralement instantanément. En conséquence, les gens (une fois qu'ils s'y sont habitués) commettent de petits changements incrémentiels, puis quand cela fonctionne, pousser une douzaine de commits en une seule fois. Ensuite, lorsque le temps de fusion arrive, le SCM dispose d'informations beaucoup plus détaillées et peut mieux résoudre les conflits en toute sécurité et automatiquement.
Et puis il y a les jolis détails qui rendent les choses encore plus faciles:
hg mv
ou hg addremove --similarity...
), tandis que Git utilise l'heuristique, mais les deux gèrent les renommages . Je peux obtenir un conflit d'arbre même avec 1 différence de chaîne dans les fichiers fusionnés! Vous devez réapprendre certains aspects de Subversion, désolé.
rename a b
fur copy a b; remove a
et à mesure que les deux le font dans un commit atomique. La différence de comportement de fusion provient de la gestion différente des cas d'angle et de Subversion permettant plus de fusions que Mercurial et Git. Enfin, Git détecte les renommages au moment de la fusion et de l'enregistrement - nous envisageons également d'ajouter cela dans Mercurial.