Je lis souvent que Hg (et Git et ...) sont meilleurs pour fusionner que SVN mais je n'ai jamais vu d'exemples pratiques où Hg / Git peut fusionner quelque chose où SVN échoue (ou où SVN a besoin d'une intervention manuelle). Pourriez-vous poster quelques listes pas à pas d'opérations de branchement / modification / validation /...- qui montrent où SVN échouerait alors que Hg / Git avance avec bonheur? Cas pratiques, pas très exceptionnels s'il vous plaît ...
Un peu de contexte: nous avons quelques dizaines de développeurs travaillant sur des projets utilisant SVN, avec chaque projet (ou groupe de projets similaires) dans son propre référentiel. Nous savons comment appliquer les branches de version et de fonctionnalités afin de ne pas rencontrer de problèmes très souvent (c'est-à-dire que nous y sommes allés, mais nous avons appris à surmonter les problèmes de Joel "un programmeur causant un traumatisme à toute l'équipe". ou "besoin de six développeurs pendant deux semaines pour réintégrer une succursale"). Nous avons des branches de publication qui sont très stables et utilisées uniquement pour appliquer des corrections de bogues. Nous avons des trunks qui devraient être suffisamment stables pour pouvoir créer une version en une semaine. Et nous avons des branches de fonctionnalités sur lesquelles des développeurs uniques ou des groupes de développeurs peuvent travailler. Oui, ils sont supprimés après la réintégration afin de ne pas encombrer le référentiel. ;)
J'essaie donc toujours de trouver les avantages de Hg / Git par rapport à SVN. J'adorerais avoir une expérience pratique, mais il n'y a pas encore de plus gros projets que nous pourrions déplacer vers Hg / Git, donc je suis obligé de jouer avec de petits projets artificiels qui ne contiennent que quelques fichiers composés. Et je recherche quelques cas où vous pouvez ressentir la puissance impressionnante de Hg / Git, car jusqu'à présent, j'ai souvent lu à leur sujet mais je n'ai pas réussi à les trouver moi-même.
Réponses:
Je n'utilise pas Subversion moi-même, mais d'après les notes de publication de Subversion 1.5: Suivi des fusions (fondamental), il semble qu'il y ait les différences suivantes par rapport au fonctionnement du suivi des fusions dans les systèmes de contrôle de version DAG complets comme Git ou Mercurial.
La fusion d'un tronc à une branche est différente de la fusion d'une branche à l'autre: pour une raison quelconque, la fusion d'un tronc à une branche nécessite une
--reintegrate
option poursvn merge
.Dans les systèmes de contrôle de version distribués comme Git ou Mercurial, il n'y a pas de différence technique entre le tronc et la branche: toutes les branches sont créées égales (il peut cependant y avoir une différence sociale ). La fusion dans les deux sens se fait de la même manière.
Vous devez fournir une nouvelle option
-g
(--use-merge-history
)svn log
etsvn blame
prendre en compte le suivi des fusions.Dans Git et Mercurial, le suivi des fusions est automatiquement pris en compte lors de l'affichage de l'historique (log) et du blâme. Dans Git, vous pouvez demander à suivre le premier parent uniquement avec
--first-parent
(je suppose qu'une option similaire existe également pour Mercurial) pour "supprimer" les informations de suivi de fusion dansgit log
.D'après ce que je comprends, la
svn:mergeinfo
propriété stocke des informations par chemin sur les conflits (Subversion est basée sur les ensembles de modifications), tandis que dans Git et Mercurial, il s'agit simplement d'objets de validation qui peuvent avoir plus d'un parent.La sous- section "Problèmes connus" pour le suivi des fusions dans Subversion suggère que la fusion répétée / cyclique / réfléchissante pourrait ne pas fonctionner correctement. Cela signifie qu'avec les histoires suivantes, la deuxième fusion pourrait ne pas faire la bonne chose ('A' peut être un tronc ou une branche, et 'B' peut être une branche ou un tronc, respectivement):
Dans le cas où l'art ASCII ci-dessus serait cassé: la branche 'B' est créée (fourchue) à partir de la branche 'A' à la révision 'x', puis la branche 'A' ultérieure est fusionnée à la révision 'y' dans la branche 'B' comme fusionner «M1», et enfin la branche «B» est fusionnée dans la branche «A» en tant que fusion «M2».
Dans le cas où l'art ASCII ci-dessus est cassé: la branche 'B' est créée (fourchue) à partir de la branche 'A' à la révision 'x', elle est fusionnée dans la branche 'A' à 'y' en tant que 'M1', et plus tard fusionné à nouveau dans la branche «A» en tant que «M2».
Subversion peut ne pas prendre en charge le cas avancé de fusion entrecroisée .
Git gère très bien cette situation en pratique en utilisant une stratégie de fusion "récursive". Je ne suis pas sûr de Mercurial.
Dans "Problèmes connus", il y a un avertissement que le suivi des fusions peut ne pas fonctionner avec les renommages de fichiers, par exemple lorsqu'un côté renomme le fichier (et peut-être le modifie) et que le deuxième côté modifie le fichier sans le renommer (sous l'ancien nom).
Git et Mercurial gèrent tous les deux ce cas très bien dans la pratique: Git utilisant la détection de renommage , Mercurial utilisant le suivi de renommage .
HTH
la source
<pre>...</pre>
bloc n'est pas en retrait comme il se doit ...--reintegrate
est obsolète.Moi aussi, j'ai cherché un cas où, disons, Subversion ne parvient pas à fusionner une branche et Mercurial (et Git, Bazaar, ...) fait ce qu'il faut.
Le livre SVN décrit comment les fichiers renommés sont fusionnés de manière incorrecte . Cela s'applique à Subversion 1.5 , 1.6 , 1.7 et 1.8 ! J'ai essayé de recréer la situation ci-dessous:
Selon le livre, la fusion devrait se terminer proprement, mais avec des données erronées dans le fichier renommé car la mise à jour
trunk
est oubliée. Au lieu de cela, j'obtiens un conflit d'arbre (c'est avec Subversion 1.6.17, la dernière version de Debian au moment de l'écriture):Il ne devrait pas y avoir de conflit du tout - la mise à jour doit être fusionnée avec le nouveau nom du fichier. Alors que Subversion échoue, Mercurial gère cela correctement:
Avant la fusion, le référentiel ressemble à ceci (de
hg glog
):Le résultat de la fusion est:
En d'autres termes: Mercurial a pris le changement de la révision 1 et l'a fusionné dans le nouveau nom de fichier de la révision 2 (
hello.en.txt
). La gestion de ce cas est bien sûr essentielle afin de prendre en charge le refactoring et le refactoring est exactement le genre de chose que vous voudrez faire sur une branche.la source
Sans parler des avantages habituels (commits hors ligne, processus de publication , ...) voici un exemple de "fusion" que j'aime bien:
Le scénario principal que je continue de voir est une branche sur laquelle ... deux tâches indépendantes sont en fait développées
(cela a commencé à partir d'une fonctionnalité, mais cela a conduit au développement de cette autre fonctionnalité.
Ou cela a commencé à partir d'un patch, mais cela a conduit au développement d'une autre fonctionnalité).
Comment fusionner une seule des deux fonctionnalités de la branche principale?
Ou comment isolez-vous les deux fonctionnalités dans leurs propres branches?
Vous pouvez essayer de générer une sorte de correctif, le problème avec cela est que vous n'êtes plus sûr des dépendances fonctionnelles qui auraient pu exister entre:
Git (et Mercurial aussi je suppose) propose l'option rebase --onto pour rebaser (réinitialiser la racine de la branche) une partie d'une branche:
D' après le message de Jefromi
vous pouvez démêler cette situation où vous avez des correctifs pour la v2 ainsi qu'une nouvelle fonctionnalité wss en:
, vous permettant de:
L'autre fonctionnalité que j'aime (qui influence les fusions) est la possibilité d' écraser les commits (dans une branche pas encore poussée vers un autre repo) afin de présenter:
Cela garantit des fusions beaucoup plus faciles, avec moins de conflits.
la source
Nous avons récemment migré de SVN vers GIT, et avons été confrontés à cette même incertitude. Il y avait beaucoup de preuves anecdotiques que GIT était meilleur, mais il était difficile de trouver des exemples.
Je peux vous dire cependant que GIT est BEAUCOUP MIEUX pour fusionner que SVN. C'est évidemment anecdotique, mais il y a un tableau à suivre.
Voici quelques-unes des choses que nous avons trouvées:
Lors de l'évaluation de GIT, nous avons effectué les tests suivants. Celles-ci montrent GIT comme le gagnant en matière de fusion, mais pas autant. En pratique, la différence est beaucoup plus grande, mais je suppose que nous n'avons pas réussi à reproduire les situations que SVN gère mal.
la source
D'autres en ont couvert les aspects les plus théoriques. Je peux peut-être donner une perspective plus pratique.
Je travaille actuellement pour une entreprise qui utilise SVN dans un modèle de développement "feature branch". C'est:
En général, cela fonctionne. SVN peut être utilisé pour un flux comme celui-ci, mais ce n'est pas parfait. Il y a certains aspects du SVN qui gênent et façonnent le comportement humain. Cela lui donne des aspects négatifs.
^/trunk
. Ces portées fusionnent les enregistrements d'informations dans toute l'arborescence et finissent par interrompre le suivi de fusion. De faux conflits commencent à apparaître et la confusion règne.svn merge
fait ce que vous voulez. La fusion de vos modifications nécessite (on nous le dit)--reintegrate
la commande de fusion. Je n'ai jamais vraiment compris ce commutateur, mais cela signifie que la branche ne peut plus être fusionnée dans le tronc. Cela signifie que c'est une branche morte et que vous devez en créer une nouvelle pour continuer le travail. (Voir la note)Ce qui a tendance à arriver, c'est qu'un ingénieur crée une succursale le jour 1. Il commence son travail et l'oublie. Quelque temps plus tard, un patron arrive et lui demande s'il peut remettre son travail dans le coffre. L'ingénieur redoute ce jour car la réintégration signifie:
... et parce que l'ingénieur fait ça aussi peu qu'il le peut, il ne se souvient pas de "l'incantation magique" pour faire chaque étape. De mauvais commutateurs et URL se produisent, et soudainement ils sont en désordre et ils vont chercher «l'expert».
Finalement, tout s'installe, et les gens apprennent à faire face aux lacunes, mais chaque nouveau démarreur traverse les mêmes problèmes. La réalité finale (par opposition à ce que j'ai exposé au début) est:
...mais...
Heureusement, l'équipe est assez petite pour faire face, mais elle ne pourrait pas évoluer. Le fait est que rien de tout cela n'est un problème avec CVCS, mais plus que parce que les fusions ne sont pas aussi importantes que dans DVCS, elles ne sont pas aussi astucieuses. Ce «frottement de fusion» provoque un comportement qui signifie qu'un modèle «Feature Branch» commence à se décomposer. Les bonnes fusions doivent être une caractéristique de tous les VCS, pas seulement de DVCS.
Selon cela, il y a maintenant un
--record-only
commutateur qui pourrait être utilisé pour résoudre le--reintegrate
problème, et apparemment la v1.8 choisit quand faire une réintégration automatiquement, et cela ne rend pas la branche morte par la suitela source
Avant la subversion 1.5 (si je ne me trompe pas), la subversion avait un inconvénient majeur en ce qu'elle ne se souvenait pas de l'historique des fusions.
Regardons le cas décrit par VonC:
Notez les révisions A et B. Supposons que vous ayez fusionné les modifications de la révision A sur la branche "wss" à la branche "v2 uniquement" à la révision B (pour une raison quelconque), mais que vous avez continué à utiliser les deux branches. Si vous tentiez de fusionner à nouveau les deux branches en utilisant mercurial, cela ne fusionnerait que les modifications après les révisions A et B. Avec la subversion, vous deviez tout fusionner, comme si vous n'aviez pas fait de fusion auparavant.
Voici un exemple tiré de ma propre expérience, où la fusion de B à A a pris plusieurs heures en raison du volume de code: cela aurait été une vraie douleur à refaire , ce qui aurait été le cas avec la subversion pré-1.5.
Une autre différence, probablement plus pertinente, dans le comportement de fusion de Hginit: Subversion Re-education :
En bref, la façon dont Mercurial analyse les différences est (était?) Supérieure à celle de la subversion.
la source