web-dev-qa-db-fra.com

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

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ù ils essaient de vous vendre quelque chose dont vous n'avez pas besoin en ayant des acteurs maladroits prétendant 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?

28
Mason Wheeler

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 grave 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.

25
Karl Bielefeldt

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 de 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, où je suis le seul développeur, je fusionne tout le temps les branches . 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 workflow axé sur la fusion est beaucoup plus agréable et plus facile à utiliser que le workflow 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.

47
Nicol Bolas

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".

De 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 (aka "the SVN way "- sans doute, la bonne façon de contrôler la version). Je crois 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é ce 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 voulez pas vouloir qu'un seul commit contienne 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 juste les modifications de l'autre d'abord, puis validez le deuxième ensemble de modifications. Notez que TortoiseSVN permet cela facilement via "Restaurer après validation".
    • Cela permet de rétablir un ensemble de modifications indépendant spécifique ET permet 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. Sinon, SVN ne gardera qu'une trace des fusions effectuées pour le sous-dossier et lorsque vous essayez de fusionner automatiquement à partir de la racine, vous pouvez obtenir avertissements concernant les révisions non fusionnées manquantes. 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, une dernière chose à propos de la fusion où, de tout ce que j'ai lu et essayé, SVN craint vraiment: 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 originale modifiée dans une autre branche ... puis les fusionner ensemble. Il ne saura simplement pas où le fichier est allé d'une manière et "oubliera" les modifications de l'autre. Une modification est évidemment insoluble (vous supprimez ou modifiez le fichier, vous ne pouvez pas faire les deux), mais l'application de 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. Est-ce mauvais ? Je ne pense pas. Il ne vous crache au 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é.

21
leokhorn

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 la branche B à la branche A, l'historique de la branche A contiendra un gros commit contenant toutes les modifications apportées explicitement à B depuis il était ramifié.

Dans les premières versions de SVN, si vous deviez fusionner à nouveau la branche B dans la branche A, vous deviez spécifier manuellement la plage de révision de la branche B que vous 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 la branche A à partir de trunk et faites quelques commits ici
  2. Créez la branche B à partir de A et faites quelques commits ici
  3. Faites quelques commits dans trunk et A
  4. Fusionner B en trunk
  5. Fusionner A en B
  6. Fusionner A en trunk
  7. Fusionner B en trunk (cela ne devrait en fait rien faire)

Le gérer correctement en utilisant le 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 ramification 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.

5
Pete

J'ai fait pas mal 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.

1
Wyatt Barnett