Pourquoi le branchement et la fusion sont-ils plus faciles dans Mercurial que dans Subversion?

92

La gestion de plusieurs fusions sur des branches dans Subversion ou CVS n'est qu'une de ces choses à expérimenter. Il est excessivement plus facile de suivre les branches et les fusions dans Mercurial (et probablement dans tout autre système distribué) mais je ne sais pas pourquoi. Quelqu'un d'autre le sait-il?

Ma question vient du fait qu'avec Mercurial vous pouvez adopter une pratique de travail similaire à celle du référentiel central Subversions / CVS et tout fonctionnera très bien. Vous pouvez faire plusieurs fusions sur la même branche et vous n'aurez pas besoin de bouts de papier interminables avec des numéros de validation et des noms de balises.

Je sais que la dernière version de Subversion a la capacité de suivre les fusions vers les branches afin que vous n'ayez pas tout à fait le même degré de tracas, mais c'était un développement énorme et majeur de leur côté et cela ne fait toujours pas tout ce que l'équipe de développement ferait. comme ça à faire.

Il doit y avoir une différence fondamentale dans la façon dont tout cela fonctionne.

Nick Pierpoint
la source

Réponses:

115

Dans Subversion (et CVS), le référentiel est avant tout. Dans git et mercurial, il n'y a pas vraiment le concept de dépôt de la même manière; ici les changements sont le thème central.

+1

Le tracas dans CVS / SVN vient du fait que ces systèmes ne se souviennent pas de la parentalité des changements. Dans Git et Mercurial, non seulement un commit peut avoir plusieurs enfants, mais il peut aussi avoir plusieurs parents!

Cela peut facilement être observé en utilisant l'un des outils graphiques, gitkou hg view. Dans l'exemple suivant, la branche # 2 a été dérivée de # 1 à la validation A, et a depuis été fusionnée une fois (à M, fusionnée avec la validation B):

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

Notez comment A et B ont deux enfants, tandis que M a deux parents . Ces relations sont enregistrées dans le référentiel. Disons que le responsable de la branche # 2 souhaite maintenant fusionner les dernières modifications de la branche # 1, il peut émettre une commande telle que:

$ git merge branch-1

et l'outil saura automatiquement que la base est B - car elle a été enregistrée dans commit M, un ancêtre de la pointe de # 2 - et qu'il doit fusionner tout ce qui s'est passé entre B et C. CVS n'enregistre pas cette information , ni SVN avant la version 1.5. Dans ces systèmes, le graphique ressemblerait à:

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

où M est juste un gigantesque commit "écrasé" de tout ce qui s'est passé entre A et B, appliqué au-dessus de M. Notez qu'après que l'acte est fait, il n'y a plus de trace (sauf potentiellement dans les commentaires lisibles par l'homme) d'où M provenait de, ni du nombre de commits qui ont été regroupés - rendant l'histoire beaucoup plus impénétrable.

Pire encore, la réalisation d' une seconde fusion devient un cauchemar: on doit comprendre ce que la base de fusion était au moment de la première fusion (et on a à savoir qu'il ya eu une fusion en premier lieu!), Alors présent que informations à l'outil afin qu'il n'essaie pas de rejouer A..B au-dessus de M. Tout cela est déjà assez difficile lorsque l'on travaille en étroite collaboration, mais est tout simplement impossible dans un environnement distribué.

Un problème (lié) est qu'il n'y a aucun moyen de répondre à la question: "X contient-il B?" où B est une correction de bogue potentiellement importante. Alors, pourquoi ne pas simplement enregistrer ces informations dans le commit, car elles sont connues au moment de la fusion!

P.-S. - Je n'ai aucune expérience avec les capacités d'enregistrement de fusion SVN 1.5+, mais le flux de travail semble être beaucoup plus artificiel que dans les systèmes distribués. Si tel est effectivement le cas, c'est probablement parce que - comme mentionné dans le commentaire ci-dessus - l'accent est mis sur l'organisation du référentiel plutôt que sur les changements eux-mêmes.

Damien Diederen
la source
6
SVN 1.5+ mettrait en effet une propriété SVN sur le commit de fusion M listant les commits fusionnés qu'il contient, en d'autres termes AB. Vous avez donc les mêmes informations.
Simon D
En quelque sorte. Techniquement, le suivi des fusions de SVN s'apparente à ce que Git appelle le «cherry-picking», avec une magie supplémentaire pour le rendre plus facile pour l'utilisateur; il est sémantiquement différent de ce que font Git, Hg et Bzr lors de la fusion. Je suppose que cela ne fait pas beaucoup de différence dans la pratique tant que vous ne vous souciez pas du DAG ( eagain.net/articles/git-for-computer-scientists ).
Damien Diederen
2
Malheur qu'il n'y a pas de bouton +100. Merci.
Charlie Flowers le
Je suppose que la fonctionnalité SVN 1.5 dont vous parlez est l'utilisation de la svn:mergeinfopropriété?
MatrixFrog
@MatrixFrog: Oui, c'est exactement ce que svn:mergeinfofait.
sleske
12

Parce que Subversion (au moins la version 1.4 et inférieure) ne garde pas trace de ce qui a été fusionné. Pour Subversion, la fusion est fondamentalement la même que tout commit tandis que sur un autre contrôle de version comme Git, ce qui a été fusionné est mémorisé.

Htanata
la source
7

N'ayant été touché par aucune des réponses déjà fournies, Hg offrait des capacités de fusion supérieures car il utilise plus d'informations lors de la fusion des modifications ( hginit.com ):

Par exemple, si je change un peu une fonction, puis que je la déplace ailleurs, Subversion ne se souvient pas vraiment de ces étapes, donc quand vient le temps de fusionner, il pourrait penser qu'une nouvelle fonction est apparue à l'improviste . Alors que Mercurial se souviendra de ces choses séparément: fonction modifiée, fonction déplacée, ce qui signifie que si vous avez également changé un peu cette fonction, il est beaucoup plus probable que Mercurial fusionnera avec succès nos modifications.

Bien sûr, se souvenir de la dernière fusion (le point abordé par la plupart des réponses fournies ici) est également une énorme victoire.

Les deux améliorations, cependant, sont discutables car subversion 1.5+ stocke des informations de fusion supplémentaires sous la forme de propriétés de subversion: ces informations disponibles, il n'y a aucune raison évidente pour laquelle la fusion de subversion ne pourrait pas implémenter la fusion avec autant de succès que Hg ou Git. Je ne sais pas si c'est le cas, mais il semble certainement que les développeurs de subversion sont sur le point de contourner ce problème.

Tomislav Nakic-Alfirevic
la source
4

Je suppose que cela pourrait être en partie dû au fait que Subversion a l'idée d'un serveur central avec une chronologie absolue des révisions. Mercurial est vraiment distribué et n'a aucune référence à une ligne temporelle absolue. Cela permet aux projets Mercurial de former des hiérarchies plus compliquées de branches pour ajouter des fonctionnalités et des cycles de test par sous-projet, mais les équipes doivent maintenant se tenir beaucoup plus activement au courant des fusions pour rester à jour car elles ne peuvent pas simplement lancer la mise à jour et en finir avec elle. .

Mal Andy
la source
3

Dans Subversion (et CVS), le référentiel est avant tout. Dans git et mercurial, il n'y a pas vraiment le concept de dépôt de la même manière; ici les changements sont le thème central.

Je n'ai pas beaucoup réfléchi à la façon dont vous implémenteriez non plus, mais mon impression (basée sur une expérience amère et de nombreuses lectures) est que cette différence est ce qui rend la fusion et le branchement tellement plus faciles dans les systèmes non basés sur un référentiel.

Stephen Darlington
la source
1

Je n'ai d'expérience qu'avec Subversion mais je peux vous dire que l'écran de fusion dans TortoiseSVN est horriblement compliqué. Heureusement, ils incluent un bouton de fonctionnement à sec afin que vous puissiez voir si vous le faites correctement. La complication réside dans la configuration de ce que vous souhaitez fusionner vers où. Une fois que vous avez configuré la fusion, la fusion se passe généralement bien. Ensuite, vous devez résoudre tous les conflits, puis valider votre copie de travail fusionnée dans le référentiel.

Si Mercurial peut faciliter la configuration de la fusion, je peux dire que cela rendrait la fusion 100% plus facile que Subversion.

Loups rouges
la source