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?
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.
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.
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:
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é.
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
A
à partir de trunk
et faites quelques commits iciB
à partir de A
et faites quelques commits icitrunk
et A
B
en trunk
A
en B
A
en trunk
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.
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.