Qu'est-ce qui est si difficile avec les fusions SVN?

28

Duplicata possible:
je suis un geek de Subversion, pourquoi devrais-je considérer ou non Mercurial ou Git ou tout autre DVCS?

De temps en temps, vous entendez quelqu'un dire que le contrôle de version distribué (Git, HG) est intrinsèquement meilleur que le contrôle de version centralisé (comme SVN) car la fusion est difficile et douloureuse dans SVN. Le fait est que je n'ai jamais eu de problème avec la fusion dans SVN, et puisque vous n'entendez que cette affirmation faite par les défenseurs de DVCS, et non par les utilisateurs réels de SVN, cela a tendance à me rappeler ces publicités odieuses à la télévision où elles essayez de vous vendre quelque chose dont vous n'avez pas besoin en faisant croire aux acteurs maladroits que la chose que vous avez déjà et qui fonctionne très bien est incroyablement difficile à utiliser.

Et le cas d'utilisation qui est invoqué invariablement est la fusion d'une succursale, ce qui me rappelle encore ces publicités de produits de paille; si vous savez ce que vous faites, vous ne devriez pas (et ne devriez jamais devoir) refusionner une branche en premier lieu. (Bien sûr, c'est difficile à faire quand vous faites quelque chose de fondamentalement mauvais et idiot!)

Donc, en excluant le cas d'utilisation ridicule de l'homme de paille, qu'y a-t-il dans la fusion SVN qui est intrinsèquement plus difficile que la fusion dans un système DVCS?

Mason Wheeler
la source
6
Je dois encore travailler dans un environnement où ils ont des mois de fusion de branches et utilisent le contrôle de version distribué. Les seuls endroits où j'ai travaillé dans ces branches à longue durée de vie ont utilisé TFS / Subversion. Je m'attends à ce que de telles branches à longue durée de vie soient également difficiles à fusionner avec les DVCS.
Oded
13
@MasonWheeler Je suis perplexe. Pourquoi utilisez-vous un VCS, alors? J'ai vu et lu qu'une des pratiques recommandées (parmi les nombreuses) est d'avoir des branches de fonctionnalités. La fusion vers le tronc est obligatoire dans ce cas. Ou ai-je mal compris quelque chose? (oui, la métaphore de l'arbre se brise, mais ce n'était pas du tout utile de commencer par IMO)
Andres F.
9
@MasonWheeler: Je pense que vous prenez un peu trop l'analogie avec l'arbre.
whatsisname
8
@MasonWheeler de combien d'environnements de développement différents avez-vous l'expérience, si vous n'avez jamais entendu parler de la fusion avec le tronc? Certains magasins ont un tronc stable et des succursales expérimentales, auquel cas la cueillette des cerises réussies est devenue un événement régulier.
itsbruce

Réponses:

25

C'est parce que svn n'avait pas les structures de données appropriées pour déterminer avec précision le dernier ancêtre commun des deux branches. Ce n'est pas un gros problème pour une branche qui n'est fusionnée qu'une seule fois, mais peut provoquer de nombreux conflits de fusion erronés dans des situations où plusieurs branches sont fusionnées plusieurs fois.

Je ne suis pas très proche de svn, mais je crois comprendre que ces problèmes techniques particuliers ont été corrigés dans les versions récentes. Cependant, il n'a pas été corrigé assez tôt pour dissiper le mythe, et les personnes qui ont essayé le DVCS pour les fusions sont restées avec lui pour d'autres raisons.

Karl Bielefeldt
la source
47

si vous savez ce que vous faites, vous ne devriez pas (et ne devriez jamais devoir) refusionner une branche en premier lieu. (Bien sûr, c'est difficile à faire quand vous faites quelque chose de fondamentalement mauvais et idiot!)

Et c'est là que réside la source de votre confusion et de tout le problème en général.

Vous dites que la fusion de succursales est "fondamentalement mauvaise et idiote". Eh bien, c'est exactement le problème: vous pensez aux branches comme des choses qui ne devraient pas être fusionnées. Pourquoi? Parce que vous êtes un utilisateur SVN qui sait que la fusion des branches est difficile . Par conséquent, vous ne le faites jamais et vous encouragez les autres à ne pas le faire. Vous avez été formé pour éviter la fusion; vous avez développé des techniques que vous utilisez pour éviter la fusion.

Je suis un utilisateur Mercurial. Même sur mes propres projets, dont je suis le seul développeur, je fusionne tout le temps les succursales . J'ai une branche de publication, dans laquelle j'ai mis un correctif. Eh bien, je fusionne cela dans la ligne principale pour que le correctif y soit.

Si j'utilisais SVN, j'adopterais une structure complètement différente de la base de code. Pourquoi? Parce que SVN rend les fusions difficiles, et donc vous développez des idiomes et des techniques pour éviter de faire des fusions complexes.

Les DVCS facilitent les fusions complexes car elles sont l' état par défaut . Tout est une branche, plus ou moins, dans un DVCS. Ainsi, la structure entière d'entre eux est construite à partir de zéro pour faciliter la fusion. Cela vous permet de développer un flux de travail qui utilise la fusion au quotidien, plutôt que le flux de travail SVN où vous n'utilisez jamais la fusion.

Le simple fait est le suivant: vous devez aborder un DVCS d'une manière différente de SVN. Vous devez utiliser les idiomes appropriés pour ces types très différents de systèmes de contrôle de version. Dans SVN, vous adoptez des idiomes qui n'impliquent pas de fusion car les fusions sont difficiles. Dans DVCS, vous adoptez des idiomes qui utilisent fréquemment des fusions car ils ne sont pas un gros problème.

Le bon outil pour le bon travail.

Le truc, c'est que le flux de travail axé sur la fusion est beaucoup plus agréable et plus facile à utiliser que le flux de travail de style SVN où vous ne fusionnez pas les choses. Il est plus facile de voir quand quelque chose de la branche release a été introduit dans la branche dev. Il est plus facile de voir les différentes interactions entre les branches. Il est facile de créer des branches de test pour des choses, puis de les couper si le test ne fonctionne pas. Etc.

Vraiment, Joel explique cela beaucoup mieux que moi . Vous devriez en avoir une bonne lecture.

Nicol Bolas
la source
15
@Mason: Comment est-ce que ce n'est pas la formation? Vous avez été formé pour utiliser SVN dans un style SVN. Et le style SVN consiste à ne pas utiliser la fusion. Ainsi, vous avez été formé pour ne pas utiliser ou même envisager de fusionner des choses. C'est pourquoi cela ne vous est jamais venu à l'esprit; parce que vous avez utilisé un système qui le rend difficile.
Nicol Bolas
5
Il y a une grande différence entre «non formé à» et «non formé à».
Mason Wheeler
8
@MasonWheeler: Non, il n'y en a pas. Si on ne vous apprend pas correctement à faire quelque chose, alors vous êtes implicitement formé à ne pas le faire. Ce n'est pas dans votre répertoire d'idiomes que vous pouvez utiliser pour résoudre un problème. Par conséquent, vous ne pouvez pas l' utiliser pour résoudre des problèmes. L'effet n'est pas différent de se faire dire de ne pas fusionner, car même si vous le vouliez, vous ne savez pas comment. La façon dont vous rejetez désinvolture un bon argument comme «le même vieux terrain fatigué» en est la preuve. Vous ne pensez pas à la fusion comme un outil; vous le considérez comme l'exception ou quelque chose d'inhabituel. Quelque chose à remettre en question plutôt qu'à utiliser.
Nicol Bolas
9
@MasonWheeler: Qui êtes-vous pour décider " ils se trompent "? Vous n'utilisez pas de DVCS, vous n'avez donc aucune expérience avec le flux de travail DVCS. Vous ne savez pas si cela est utile aux programmeurs ou non, car vous n'avez aucune expérience avec cela. Alors, quelle autorité avez-vous pour dire que c'est "faux" juste parce que SVN ne le permet pas? C'est comme dire que les classes, les fonctions virtuelles et les modèles sont incorrects parce que C n'en a pas.
Nicol Bolas
3
@MasonWheeler: comme ça? : P . La ramification et la fusion SVN font la même chose - la métaphore est déjà cassée. Je ne vois pas vraiment comment quelque chose comme ça est si difficile à comprendre, surtout si cela inclut des commentaires de commit sensés.
naught101
21

Il n'y a rien de trop difficile à fusionner SVN ... plus ... si vous suivez la bonne philosophie

Ce que je vois dans la plupart des autres réponses semble provenir de personnes qui n'ont pas utilisé SVN depuis un certain temps. Comme quelqu'un le mentionne avec précision: "il n'a pas été corrigé assez tôt pour dissiper le mythe".

D'après mon expérience actuelle de l'utilisation de SVN 1.6 à 1.8 sur un projet hérité dont j'ai hérité récemment, SVN a fait un long chemin pour rendre la fusion beaucoup plus facile. Ce n'est pas infaillible, cependant, et je pense que les utilisateurs ne s'écartent pas facilement de l'utilisation prévue.

Alors que je connaissais assez bien SVN et que j'avais également essayé Mercurial pour des projets personnels entre-temps, je n'avais jamais fait beaucoup de branchements dans SVN avant ce projet. Il y a eu pas mal d'essais et d'erreurs et j'ai eu beaucoup de conflits de fusion inattendus quand j'ai commencé.

En fin de compte, cependant, je me suis rendu compte que chaque fois que j'en obtenais un (ou un autre problème), c'était parce que je n'avais pas fait les choses correctement (alias "la manière SVN" - sans doute, la bonne façon de contrôler la version). Je pense que c'est là que réside la difficulté: vous ne pouvez pas faire ce que vous voulez de manière non organisée et vous attendre à ce que SVN fonctionne parfaitement, en particulier avec les fusions. Les fusions nécessitent une discipline rigoureuse de la part des utilisateurs avant de montrer leur véritable pouvoir.

Voici des choses que j'ai remarquées comme de fortes recommandations, sinon des exigences, pour une utilisation propre des fusions:

  • Utilisez une version récente de SVN (1.6 et plus à mon avis). De plus en plus d'automatisation et de contrôles sont effectués pour vous.
  • Utilisez la structure par défaut "tronc, branches, tags" et appliquez sa philosophie (ne vous engagez pas sur les tags). SVN ne vérifiera rien pour vous. Si vous utilisez une balise comme branche (c'est dans cet état que j'ai trouvé le référentiel de projet), cela peut toujours fonctionner, mais vous devez être cohérent.
  • Sachez ce que sont les branches et quand les créer. Même chose avec les balises.
  • Gardez les branches latérales à jour avec leur branche source (généralement le tronc, mais vous pouvez vous dériver de n'importe quelle branche techniquement). Ceci est obligatoire SI vous voulez que SVN fasse des fusions automatiques. SVN 1.8 vous empêche en fait de fusionner automatiquement si les choses ne sont pas à jour, et aussi si vous avez des modifications en attente dans votre copie de travail (ce comportement semble avoir à nouveau disparu en 1.8.5).
  • Faites des commits «appropriés». Ils ne doivent contenir que des modifications sur un concept très spécifique. Autant que possible, ils devraient contenir une petite quantité de changement. Vous ne pas vouloir d'avoir un seul commettras contiennent des modifications sur deux bugs indépendants par exemple. Si vous avez déjà corrigé les deux et qu'ils sont dans le même fichier, vous devez stocker les modifications d'un bogue afin de pouvoir valider uniquement les modifications de l'autre en premier, puis valider le deuxième ensemble de modifications. Notez que TortoiseSVN permet cela facilement via "Restaurer après validation".
    • Cela permet de revenir à un ensemble de modifications indépendant spécifique ET de fusionner uniquement un tel ensemble dans une autre branche. Oui, SVN vous permet de fusionner des révisions choisies avec soin.
  • Si vous utilisez des sous-branches (ramification du tronc, puis ramification de cette nouvelle branche), respectez la hiérarchie. Si vous mettez à jour la sous-branche avec le tronc ou vice versa, vous aurez du mal. Les fusions doivent être montées en cascade vers le bas ou vers le haut de la hiérarchie.
    • Après quelques mois d'expérimentation, je peux garantir que cela pourrait être la partie la plus importante. J'ai essayé de créer deux sous-branches à partir du même tronc, puis de fusionner les bits entre les sous-branches, ou parfois entre les sous-sous-branches de chaque côté. Cela peut déclencher SVN (ou l'utilisateur). Cela peut fonctionner correctement si vous fusionnez des révisions spécifiques. La fusion automatique peut avoir des problèmes avec elle.
    • J'ai eu des problèmes spécifiquement lors de la synchronisation de la sous-branche A avec le tronc, puis d'essayer de fusionner quelque chose de la sous-branche A dans la sous-branche B. SVN semble penser que la révision "synchroniser à partir du tronc" devrait légitimement être fusionnée dans la sous-branche B et cela conduit à une masse de conflits.
  • Autant que possible, fusionnez depuis la racine de la branche. Dans le cas contraire, SVN ne garder une trace des fusions réalisées pour le sous-dossier et quand vous faites essayer d'auto-fusion à partir de la racine, vous pouvez obtenir des avertissements sur l' absence de révisions non fusionnées. C'est réparable en fusionnant simplement ceux-ci à partir de la racine, mais évitez au mieux la confusion.
  • Faites attention à quelle branche vous vous engagez. Si vous utilisez Switch pour que votre copie de travail pointe vers différentes branches dans le temps, assurez-vous où vous vous engagez.
    • C'est particulièrement mauvais si vous ne vouliez vraiment pas le changement dans cette branche. Je ne suis toujours pas clair sur celui-ci, mais selon la façon dont vous vous en débarrassez / le transférez dans la bonne branche (retour, fusion), vous pouvez obtenir quelque chose de désordonné. C'est réparable, mais vous devrez soit fusionner révision par révision pour éviter ou résoudre immédiatement les conflits potentiels, ou vous devrez résoudre un conflit éventuellement plus complexe après la fusion automatique.
  • Ne laissez pas les branches intactes trop longtemps. En fait, ce n'est pas une question de temps mais de combien de révisions ont été commises à la branche et au tronc et combien ont changé dans celles-ci. Les fusions entre deux branches, les fusions à 3 voies, sont toujours comparées à la révision commune la plus récente entre les branches. Plus il y a de changements entre les deux, plus la fusion automatique échouera. C'est, bien sûr, bien pire si vous avez changé la structure de votre code entre-temps (fichiers déplacés ou renommés).

Si vous ne suivez pas ce qui précède, vous risquez probablement de rencontrer des conflits. Ils sont toujours solubles, mais pas très amusants à passer du temps.

Oh, encore une chose à propos de la fusion où, de tout ce que j'ai lu et essayé, SVN est vraiment nul: fichiers / dossiers supprimés / déplacés / renommés. Apparemment , SVN ne peut toujours pas traiter un fichier renommé, supprimé ou déplacé dans une branche, et sa version d'origine modifiée dans une autre branche ... puis les fusionner. Il ne saura simplement pas où le fichier est allé dans un sens et "oubliera" les changements dans l'autre sens. Une modification est évidemment insoluble (vous supprimez ou modifiez le fichier, vous ne pouvez pas faire les deux), mais l'application des modifications aux fichiers déplacés / renommés devrait fonctionner et ce n'est pas le cas. Espérons que cela sera bientôt corrigé.

Donc, dans l'ensemble, la fusion de SVN est-elle facile? Je suppose que non. Pas de manière insouciante, c'est sûr. C'est mauvais ? Je ne pense pas. Il ne crache en arrière dans votre visage que lorsque vous l'utilisez mal et que vous ne pensez pas assez à ce que vous faites.

Sur cette base, je peux voir pourquoi les gens pourraient préférer Mercurial (par exemple) car il est un peu plus indulgent à propos de ces choses de mon expérience et a tout automatisé dès le départ (au moins à partir des premières versions avec lesquelles j'ai commencé). SVN a rattrapé un peu de retard, cependant, ce n'est plus digne d'être autant critiqué.

leokhorn
la source
Conflits d'arbres - oui, SVN a du mal avec ceux-ci, bien que TBH le fasse tous les autres SCM. Git a quelques heuristiques pour essayer de déterminer si les fichiers qui ont été renommés ou déplacés sont les mêmes, mais il ne le fait pas (ne peut pas!) Toujours faire les choses correctement. Je pense que SVN devrait faire un effort pour faciliter la résolution de ces conflits.
gbjbaanb
@gbjbaanb: Il propose "Repair Move" comme Mercurial, bien qu'il n'offre pas d'heuristique. Vous devez lui dire quels fichiers supprimés et ajoutés sont en fait les mêmes. Certainement matière à amélioration.
leokhorn
Tout cela sonne bien lorsque vous êtes la seule personne à travailler sur le projet ... Mais si vous avez une équipe de bonne taille et qu'ils l'utilisent tous, la "méthode SVN" (sur laquelle personne ne semble d'accord sur ce que c'est) fusionne sont toujours un PITA. Le fait est que svn ne prend pas vraiment bien en charge le flux de travail de branchement. La "façon SVN" serait de ne même pas créer de branches et d'utiliser un SDLC en cascade. Cela étant dit, j'ai eu des problèmes avec les fusions de Git dans le passé sur de grands projets avec plusieurs personnes travaillant dessus. Mais, ils semblaient encore beaucoup moins douloureux.
ryoung
D'après mon expérience, si vous travaillez avec des gens qui ne se soucient pas du fonctionnement du système de contrôle de version, SVN est beaucoup plus facile à utiliser au quotidien. Je n'ai travaillé que sur quelques équipes DVCS mais invariablement un nombre important de l'équipe n'a pas un bon comportement de contrôle des révisions et cela pollue le référentiel pour tout le monde. Dans Subversion, les personnes non formées restent généralement à l'écart des succursales, ce qui permet aux «experts» de le faire pour eux et ils sont gérés de manière appropriée. Certes, cette expérience est la mienne seule et je préférerais travailler uniquement avec des programmeurs qui savaient comment leurs outils fonctionnaient ...
dash-tom-bang
5

Les modèles de données internes sont fondamentalement différents.

Fondamentalement, dans SVN, lorsque vous regardez l'historique d'une branche, vous ne voyez que ce qui s'est passé dans cette branche. Ainsi, lorsque vous fusionnez de branche Ben branche A, l'historique de branche Acontiendra une grande validation contenant toutes les modifications apportées explicitement Bdepuis qu'elle a été branchée.

Dans les premières versions de SVN, si vous deviez fusionner une branche Ben branche Aune fois de plus, vous deviez spécifier manuellement la plage de révision de la branche que Bvous vouliez fusionner afin d'éviter de fusionner deux fois les mêmes révisions. Le développeur intelligent utiliserait bien sûr un message de validation comme «Fusionné dans B: 1234».

SVN 1.5 "corrige" cela. Mais cela n'a pas changé la façon dont les fusions sont appliquées fondamentalement. Il a simplement ajouté des métadonnées supplémentaires à la branche A, permettant à SVN de savoir que la révision 1234 avait été fusionnée, permettant à SVN de choisir automatiquement la plage de révision correcte.

Mais cette solution est essentiellement une solution de contournement pour un modèle de données qui, fondamentalement, ne prend pas en charge le suivi de ce qui a été fusionné.

La fusion de deux branches est un exemple relativement simple. Mais imaginer ce scénario plus complexe

  1. Créez une branche à Apartir de trunket faites quelques commits ici
  2. Créez une branche à Bpartir de Aet faites quelques commits ici
  3. Faites quelques commits trunketA
  4. Fusionner Bdanstrunk
  5. Fusionner AdansB
  6. Fusionner Adanstrunk
  7. Fusionner Bdans trunk(cela ne devrait pas faire quoi que ce soit)

Le gérer correctement à l'aide du modèle de métadonnées devient extrêmement complexe (je ne sais pas si SVN gère effectivement ce scénario correctement, et je ne me sens pas enclin à le tester).

La gestion de ce scénario dans git est extrêmement simple.

Dans git, chaque fois que vous validez, l'objet interne représentant cette validation contient une référence à la tête précédente. Lorsque vous fusionnez dans une branche, la validation contient des références à la tête précédente de toutes les branches fusionnées (vous pouvez fusionner plusieurs branches à la fois dans git)

Par conséquent, lorsque vous examinez l'historique d'un seul commit dans git, vous pouvez voir tout l'historique, vous pouvez voir quand il a été ramifié, quand il a été fusionné, et vous pouvez voir l'historique des deux branches entre la branche et la fusion.

Ainsi, lors de la fusion dans une branche qui a été partiellement fusionnée, il est extrêmement simple de déterminer ce qui a déjà été fusionné et ce qui ne l'a pas déjà été.

Je n'ai aucune expérience avec Mercurial, mais je soupçonne que son fonctionnement interne est similaire à Git.

Donc, fondamentalement, pour SVN, c'était un objectif de conception de rendre la branche bon marché. Mais dans git, c'était un objectif de conception de rendre la fusion bon marché.

Enfin, la dernière fois que j'ai utilisé SVN, il n'a pas pu gérer les fusions, où un fichier a été renommé dans une branche et modifié dans une autre.

Pete
la source
1

J'ai fait un peu de fusion de SVN - y compris des branches de développement et de publication de longue durée. Dans l'ensemble, j'ai survécu. La fusion est toujours délicate, mais avec DCVS, l'inconvénient n'est pas horriblement mauvais - tout est local, alors mettez à jour une bonne révision connue et continuez. Alors qu'avec SVN, beaucoup de choses se passaient du côté serveur, donc la récupération était moche - généralement cela impliquait d'effacer la copie locale puis de vérifier une nouvelle branche propre pour l'essayer à nouveau. Ce n'était pas mal dans mon cas - une connexion gigabit à la boîte SVN aide. Mais nous avons eu certains entrepreneurs qui ont eu beaucoup de problèmes avec cela car ils étaient sur des connexions lentes, donc tout a pris une éternité, y compris les fusions.

Wyatt Barnett
la source
extrapoler sur la connexion lente, travailler à partir d'un serveur distant hors site entraîne également des erreurs de connexion abandonnées lors de grandes mises à jour> <Pas amusant du tout.
jxramos
-1

Oui, je fais ça aussi. J'ai actuellement 12 machines virtuelles pour différentes versions (branches) du projet dont je fais partie au travail. Lorsque je dois corriger un bogue dans une ancienne version, je corrige le bogue, puis fusionne ce commit dans les branches pour les versions plus récentes. Mais c'est maintenant la fusion d'une branche entière, ce dont je parle ici.

Ici se trouve l'une des très belles choses sur git. Ce n'est pas hérité du DVCS, c'est juste quelque chose d'excitant. Vous pouvez fusionner des révisions spécifiques de n'importe quelle branche dans une autre branche. Il prend simplement le diff et l'applique à l'autre branche, mais fait le suivi et est beaucoup plus automatique.

Donc, si vous avez la branche 2.0 et la branche 3.0 et découvrez un bogue dans 2.0, vous pouvez le corriger dans 2.0 et prendre l'ensemble des révisions qui le résolvent et fusionner uniquement ces révisions dans la branche 3.0. Je ne pense pas que SVN ait d'autre moyen que de prendre manuellement les différences pour chaque révision et de les appliquer

Bien sûr, l'algorithme de fusion automatique semble également fonctionner beaucoup plus facilement et git a été construit à partir du sol sur le modèle "créer une branche pour toutes choses", donc la ramification est vraiment très simple et facile. Il semble naturel de se ramifier souvent avec la légèreté de ses branches

Earlz
la source
De plus, j'imagine que mercurial a des fonctionnalités similaires
Earlz
2
En fait, vous pouvez faire exactement la même chose dans SVN. Je le fais tout le temps. La commande SVN Merge peut extraire une révision (ou plage de révisions) d'une branche différente et l'appliquer à votre copie de travail, puis vous la validez.
Mason Wheeler
2
@MasonWheeler Gardez à l'esprit qu'une grande partie du sentiment anti-svn était dirigé vers les versions antérieures à 1.5 (lorsque svn a obtenu le suivi des fusions). Et bien sûr, beaucoup de choses ne sont que du fanboyisme inutile ...
yannis
3
@MasonWheeler voir aussi stackoverflow.com/a/4215199/69742 Ce post se résume à DVCS garde une trace des changements et non des versions . Les ensembles de modifications sont intrinsèquement faciles à prendre et à fusionner ... les versions ne sont pas tellement parce qu'elles nécessitent du contexte
Earlz
@MasonWheeler oh et celui-ci: stackoverflow.com/questions/2471606/…
Earlz