Meilleure stratégie de branchement lors de l'intégration continue?


100

Quelle est la meilleure stratégie de branchement à utiliser lorsque vous souhaitez effectuer une intégration continue?

  1. Branchement des versions: développer sur le tronc, conserver une branche pour chaque version.
  2. Branchement des fonctionnalités: développez chaque fonctionnalité dans une branche distincte, ne fusionnez qu'une fois stable.

Est-il judicieux d'utiliser ces deux stratégies ensemble? Comme dans, vous branchez pour chaque version mais vous branchez aussi pour les grandes fonctionnalités? L'une de ces stratégies s'intègre-t-elle mieux avec une intégration continue? L'utilisation de l'intégration continue aurait-elle même un sens lors de l'utilisation d'un coffre instable?


2
Remarque: certains diront que même si de nouvelles fonctionnalités sont ajoutées, tout devrait toujours être stable. D'un autre côté, cela pourrait être quelque peu idéaliste.
Keith Pinson

Réponses:


21

Je trouve le sujet vraiment intéressant car je compte beaucoup sur les branches dans mon travail quotidien.

  • Je me souviens que Mark Shuttleworth proposait un modèle pour garder la branche principale vierge tout en allant au-delà de l'IC conventionnelle. J'ai posté à ce sujet ici .
  • Depuis que je suis familier avec Cruise Control, j'ai également blogué sur les branches de tâches et CI ici . C'est un tutoriel étape par étape expliquant comment le faire avec Plastic SCM .
  • Enfin, j'ai trouvé certains des sujets sur CI (et potentiellement parler de branchement) dans le livre de Duvall sur CI très intéressants aussi .

J'espère que vous trouverez les liens intéressants.


Nous avons ajouté le support à Bamboo pour faire des branches par tâche codicesoftware.blogspot.com/2012/02/… , et il semble que leur dernière version le fera nativement avec plusieurs contrôles de version, y compris dvcs.
pablo

20

La réponse dépend de la taille de votre équipe et de la qualité de votre contrôle de code source et de la possibilité de fusionner correctement des ensembles de modifications complexes. Par exemple, dans le contrôle de source de branche complet comme CVS ou SVN, la fusion peut être difficile et vous pourriez être mieux avec le premier modèle, tandis que si vous utilisez un système plus complexe comme IBM ClearCase et avec une plus grande taille d'équipe, vous pourriez être meilleur avec le second modèle ou une combinaison des deux.

Personnellement, je séparerais le modèle de branche de fonctionnalité, où chaque fonctionnalité principale est développée sur une branche distincte, avec des sous-branches de tâche pour chaque changement effectué par un développeur individuel. Au fur et à mesure que les fonctionnalités se stabilisent, elles sont fusionnées avec le tronc, que vous gardez raisonnablement stable et en réussissant tous les tests de régression à tout moment. Alors que vous approchez de la fin de votre cycle de publication et que toutes les branches de fonctionnalités fusionnent, vous stabilisez et branchez une branche du système de publication sur laquelle vous ne faites que des corrections de bogues de stabilité et des backports nécessaires, tandis que le tronc est utilisé pour le développement de la prochaine version et vous à nouveau bifurquez pour de nouvelles branches de fonctionnalités. Etc.

De cette façon, le tronc contient toujours le dernier code, mais vous parvenez à le garder raisonnablement stable, en créant des étiquettes stables (balises) sur les changements majeurs et les fusions de fonctionnalités, les branches de fonctionnalités sont un développement rapide avec une intégration continue et des sous-branches de tâches individuelles peuvent être souvent actualisé à partir de la branche des fonctionnalités pour que tout le monde travaille sur la même fonctionnalité en synchronisation, tout en n'affectant pas simultanément les autres équipes travaillant sur différentes fonctionnalités.

En même temps, vous avez à travers l'historique un ensemble de branches de publication, où vous pouvez fournir des backports, un support et des corrections de bogues pour vos clients qui, pour une raison quelconque, restent sur les versions précédentes de votre produit ou même simplement sur la dernière version publiée. Comme pour le tronc, vous ne configurez pas l'intégration continue sur les branches de publication, elles sont soigneusement intégrées après avoir réussi tous les tests de régression et autres contrôles de qualité de publication.

Si, pour une raison quelconque, deux fonctionnalités sont co-dépendantes et nécessitent des modifications l'une de l'autre, vous pouvez envisager de développer les deux sur la même branche de fonctionnalité ou d'exiger que les fonctionnalités fusionnent régulièrement des parties stables du code avec le tronc, puis actualisent les modifications de tronc pour échanger du code entre les branches du tronc. Ou si vous avez besoin d'isoler ces deux fonctionnalités des autres, vous pouvez créer une branche commune à partir de laquelle vous branchez ces branches de fonctionnalités et que vous pouvez utiliser pour échanger du code entre les fonctionnalités.

Le modèle ci-dessus n'a pas beaucoup de sens avec des équipes de moins de 50 développeurs et un système de contrôle de source sans branches clairsemées et une capacité de fusion appropriée comme CVS ou SVN, ce qui ferait de tout ce modèle un cauchemar à configurer, gérer et intégrer.


5
Je ne sais pas si je conviens que ce que vous décrivez n'a pas de sens pour les équipes de moins de 50 développeurs. Je vois également des avantages pour des équipes beaucoup plus petites. +1
Aardvark

2
Bien sûr, il y a des avantages pour les équipes de toute taille. La question est de savoir à quelle taille d'équipe les avantages l'emportent sur les coûts associés à un processus lourd.
Jiri Klouda

Ceci est similaire au modèle GitFlow et / ou GitHubFlow. Je ne pense pas que ces modèles facilitent l'intégration continue (CI). À mon avis, le développement basé sur le tronc est une amélioration significative de ces modèles.
Yani

Vous pouvez voir que ce commentaire est en fait antérieur à la version originale de git flow. Je ne sais pas trop ce que vous entendez par «mieux». J'ai soutenu des équipes de 1, 5, 25, 150, 1 000 et 20 000 développeurs travaillant sur des projets qui ont été intégrés dans une certaine mesure. Les exigences varient et «mieux» est un terme très relatif. Avez-vous déjà besoin de rétroporter du code? Correctifs de sécurité? Sinon, votre vie est simple. Le SaaS est le résultat direct des restrictions imposées par le développement basé sur le tronc. Les indicateurs de fonctionnalités sont tout aussi complexes que les branches de fonctionnalités. Sauf que vous ne découvrez des clients que lorsqu'une permutation entre eux se brise.
Jiri Klouda

9

Personnellement, je trouve beaucoup plus propre d'avoir un tronc stable et de faire des branchements. De cette façon, les testeurs et autres peuvent rester sur une seule «version» et mettre à jour à partir du tronc pour tester toute fonctionnalité dont le code est complet.

De plus, si plusieurs développeurs travaillent sur différentes fonctionnalités, ils peuvent tous avoir leurs propres branches distinctes, puis fusionner avec le tronc une fois terminé et envoyer une fonctionnalité à tester sans que le testeur n'ait à passer à plusieurs branches pour tester différentes fonctionnalités.

En prime, il existe un certain niveau de test d'intégration qui vient automatiquement.


De plus, avez-vous toujours des branches et des balises pour chaque version majeure? Ou simplement taguer?
KingNestor

1
Cela fonctionne bien avec CI tant que les branches de fonctionnalités sont fusionnées dans le tronc avec une certaine discipline afin de ne pas avoir de versions interrompues. Je fais des branches et des balises pour chaque version de production qui ne sera utilisée que pour la correction de bogues. Cela peut être immédiatement fusionné dans le coffre stable.
Adnan le

@king Je dirais que cela dépend probablement de ce que vous appelez la version majeure, mais dans les deux cas, vous pouvez taguer, et
créer une

5

Je pense que l'une ou l'autre de ces stratégies peut être utilisée avec un développement continu à condition que vous vous souveniez de l'un des principes clés que chaque développeur s'engage chaque jour sur le tronc / la ligne principale.

http://martinfowler.com/articles/continuousIntegration.html#EveryoneCommitsToTheMainlineEveryDay

ÉDITER

J'ai lu ce livre sur CI et les auteurs suggèrent que le branchement par version est leur stratégie de branchement préférée. Je suis d'accord. Le branchement par fonctionnalité n'a aucun sens pour moi lorsque j'utilise CI.

Je vais essayer d'expliquer pourquoi je pense de cette façon. Supposons que trois développeurs prennent chacun une branche pour travailler sur une fonctionnalité. Chaque fonctionnalité prendra plusieurs jours ou semaines pour se terminer. Pour s'assurer que l'équipe s'intègre en permanence, elle doit s'engager auprès de la branche principale au moins une fois par jour. Dès qu'ils commencent à faire cela, ils perdent l'avantage de créer une branche de fonctionnalités. Leurs modifications ne sont plus séparées de toutes les modifications des autres développeurs. Cela étant, pourquoi se donner la peine de créer des branches de fonctionnalités en premier lieu?

L'utilisation de la création de branches par version nécessite beaucoup moins de fusion entre les branches (toujours une bonne chose), garantit que toutes les modifications sont intégrées dès que possible et (si elles sont effectuées correctement) garantit que votre base de code est toujours prête à être publiée. L'inconvénient du branchement par version est que vous devez être beaucoup plus prudent avec les changements. Par exemple, une refactorisation importante doit être effectuée de manière incrémentielle et si vous avez déjà intégré une nouvelle fonctionnalité que vous ne voulez pas dans la prochaine version, elle doit être masquée à l'aide d'une sorte de mécanisme de basculement de fonctionnalité .

UNE AUTRE MODIFICATION

Il y a plus d'un avis sur ce sujet. Voici un article de blog qui est une fonctionnalité professionnelle de branchement avec CI

http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/


intéressant, je ne trouve plus ce message.
Jirong Hu

5

Les branches de version sont très utiles, et même absolument nécessaires, si vous avez besoin de gérer plusieurs versions de votre application.

Les branches de fonctionnalités sont également très pratiques, notamment si un développeur doit travailler sur un énorme changement, tandis que d'autres publient encore de nouvelles versions.

Donc, pour moi, utiliser les deux mécanismes est une très bonne stratégie.

Lien intéressant du livre de SVN .


4

J'ai récemment aimé ce modèle lors de l'utilisation de git. Bien que votre question soit étiquetée "svn", vous pourrez peut-être en faire un certain usage.

L'intégration continue peut dans une certaine mesure se produire dans la branche "develop" (ou comme vous l'appelez) de ce modèle, bien que le fait d'avoir de longues branches de fonctionnalités pour les versions futures ne le rendrait pas si rigide que de considérer chaque changement survenant dans le code quelque part. Reste à savoir si vous voulez vraiment cela. Martin Fowler le fait.


2

L'intégration continue ne doit en aucun cas être un facteur déterminant votre stratégie de branchement. Votre approche de branchement doit être choisie en fonction de votre équipe, du système en cours de développement et des outils à votre disposition.

Ayant dit cela ...

  • il n'y a aucune raison pour que CI ne puisse pas être utilisé dans les deux approches que vous décrivez
  • ces approches fonctionnent assez bien en combinaison
  • aucun des deux ne fonctionne "mieux" que l'autre
  • L'IC prend tout son sens avec un coffre instable

Tout cela a été répondu dans la quatrième question de la page à partir de laquelle vous avez extrait les diagrammes: http://blogs.collab.net/subversion/2007/11/branching-strat/


2

Tant que vous comprenez les principes, vous pouvez toujours réinventer les meilleures pratiques. Si vous ne comprenez pas les principes, les meilleures pratiques vous mèneront aussi loin avant de s'effondrer en raison d'exigences externes contradictoires.

Pour une meilleure introduction dans le modèle principal, lisez ceci: https://web.archive.org/web/20120304070315/http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf

Lisez le lien. Une fois que vous avez les bases, lisez l'article suivant du vénérable Henrik Kniberg. Cela vous aidera à associer le modèle principal à une intégration continue.

http://www.infoq.com/articles/agile-version-control


Le chapitre O'Reilly n'est plus accessible
Jason S

1

Lorsque nous avons créé notre équipe, nous avons hérité d'une stratégie basée sur les versions du fournisseur qui a initialement développé le système dont nous étions sur le point de prendre en charge. Cela a fonctionné jusqu'au moment où nos clients ont demandé que plusieurs fonctionnalités développées ne soient pas incluses dans une version (environ 250 000 lignes de code, environ 2500 fichiers, Scrum avec XP SDLC).

Ensuite, nous avons commencé à examiner les branches basées sur les fonctionnalités. Cela a également fonctionné pendant un certain temps - environ 2 mois jusqu'au moment où nous nous sommes rendu compte que notre processus de test de régression prendrait plus de 2 semaines, ce qui, combiné à l'incertitude de ce qui serait publié, a créé un énorme inconvénient.

Le dernier «clou dans le cercueil» des stratégies SC pures est venu lorsque nous avons décidé que nous devrions avoir 1. un tronc stable et 2. La production devrait contenir des BINAIRES testés ST, UAT et régression (pas seulement la source - pensez CC.)

Cela nous a conduit à concevoir une stratégie hybride entre les stratégies SC basées sur les fonctionnalités et les versions.

Nous avons donc un coffre. Chaque sprint, nous divisons la branche de sprint (pour les non-agiles - un sprint est juste un effort de développement limité dans le temps avec une sortie variable basée sur la complexité.) À partir de la branche de sprint, nous créons les branches de fonctionnalités et le développement parallèle commence en elles. Une fois que les fonctionnalités sont complètes et le système testé, et que nous avons l'intention de les déployer, elles sont fusionnées dans la branche sprint - certaines peuvent flotter sur plusieurs sprints, généralement les plus complexes. Une fois que le sprint est proche de sa fin et que les fonctionnalités sont complètes ... nous "renommons" la branche du sprint en "régression" (cela permet à CruiseControl de la récupérer sans aucune reconfiguration), puis les tests de régression / intégration commencent sur le cc-build OREILLE. Quand tout cela est fait, il entre en production.

En bref, les branches basées sur les fonctionnalités sont utilisées pour développer, tester le système et les fonctionnalités UAT. La branche sprint (en fait la branche release) est utilisée pour fusionner sélectivement les fonctionnalités à la demande et les tests d'intégration.

Maintenant, voici une question à la communauté - nous avons évidemment du mal à effectuer une intégration continue en raison du fait que le développement se produit sur de nombreuses succursales et des frais généraux de reconfiguration de CruiseControl. Quelqu'un peut-il suggérer et conseiller?


Je ne suis pas nécessairement d'accord avec les conclusions, mais merci pour la discussion sur votre processus. Il n’existe pas de solution universelle.
RaoulRubin

0

Selon moi, vous voulez avoir un ensemble limité de branches sur lesquelles vous pouvez vous concentrer. Puisque vous voulez des tests, des métriques de qualité du code et de nombreuses choses intéressantes à exécuter avec les builds, avoir trop de rapports vous fera probablement manquer des informations.

Quand et quoi créer une branche, dépend généralement de la taille de l'équipe et de la taille des fonctionnalités développées. Je ne pense pas qu'il y ait de règle d'or. Assurez-vous d'utiliser une stratégie dans laquelle vous pouvez obtenir des commentaires tôt / souvent, et qui inclut la qualité impliquée dès le début des fonctionnalités. La qualité signifie qu'au fur et à mesure que vous automatisez au fur et à mesure que l'équipe se développe, si vous branchez pour un grand ensemble de fonctionnalités qu'une équipe est en train de construire, vous devez également impliquer la qualité dans l'équipe.

ps D'où avez-vous obtenu ces références d'approche? - ne pense pas que ces graphiques représentent toutes les options

Mise à jour 1: Expliquer pourquoi j'ai dit que ce n'était pas une règle d'or. Fondamentalement, pour des équipes relativement petites, je l'ai trouvé le mieux en utilisant une approche mixte. Des branches de fonctionnalités sont créées s'il s'agit de quelque chose de long et une partie de l'équipe continuera d'ajouter des fonctionnalités plus petites.


Il en a aussi d'autres. Mais j'ai l'impression que le branchement de fonctionnalités et le branchement de version sont les deux plus courants.
KingNestor

0

Dave Farley , auteur de Continuous Delivery , a qualifié le Trunk Based Development (TBD) de la pierre angulaire de l'intégration continue (CI) et de la livraison continue (CD). Il dit:

Toute forme de branchement est antithétique à l'intégration continue.

Il dit aussi,

Le branchement des fonctionnalités est très agréable du point de vue d'un développeur individuel mais sous-optimal du point de vue d'une équipe. Nous aimerions tous pouvoir ignorer ce que tout le monde fait et continuer notre travail. Malheureusement, le code n'est pas comme ça. Même dans des bases de code très bien factorisées avec une belle séparation des problèmes et des composants merveilleusement faiblement couplés, certains changements affectent d'autres parties du système.

Le développement basé sur le tronc (TBD) est la pratique consistant à intégrer les changements de code dans le tronc (alias, maître, ligne principale) au moins une fois par jour - de préférence plusieurs fois par jour. L'intégration continue (CI) est une pratique similaire, sauf qu'elle implique également de vérifier les changements de code à l'aide de tests automatisés. La meilleure stratégie de branchement pour cela est de travailler directement sur le tronc et d'effectuer des révisions de code via la programmation par paires . Si, pour une raison quelconque, vous ne pouvez pas vous associer ou si vous voulez vraiment créer des branches, assurez-vous que vos branches sont de courte durée (moins d'un jour).

Je travaille sur Trunk, «master» dans mes dépôts GIT. Je m'engage à maîtriser localement et à pousser immédiatement, lorsque je suis en réseau, à mon repo principal central où CI s'exécute. C'est tout!

Pour les fonctionnalités volumineuses (c'est-à-dire celles qui prennent plus d'une journée), essayez de les diviser en petits morceaux de logique qui peuvent être intégrés dans le coffre sans casser le logiciel. Vous pouvez également utiliser des techniques telles que le marquage des fonctionnalités et le branchement par abstraction qui vous permettent de déployer un travail incomplet sans affecter les utilisateurs finaux.

J'utilise la branche par abstraction, la libération d'obscurité et parfois des indicateurs de fonctionnalité. Ce que j'obtiens en retour, ce sont des retours rapides et définitifs (du moins pour la qualité de mes tests).


Dave Farley et Jez Humble se trompent tout simplement dans leur position sur la ramification. La raison en est qu'il encode l'hypothèse importante "vous n'aurez jamais à manipuler le code au niveau de la fonctionnalité et si, alors il est normal que ce soit une opération coûteuse" et ils basent leur évaluation sur une autre hypothèse "la fusion est trop coûteuse avec l'automatisation fusionne étant presque impossible à grande échelle ". Si ces deux hypothèses ne sont pas vraies, si vous vivez dans un monde où la fusion est bon marché, mais que vous devez manipuler le code au niveau des fonctionnalités pour les ports arrière et les correctifs de sécurité, alors leurs déclarations échouent. C'est un cas rare.
Jiri Klouda

Certaines entreprises doivent également faire évoluer les fonctionnalités vers les versions futures, après que ces fonctionnalités aient rencontré des obstacles lors de la mise en œuvre et retardent une version. Parfois, il existe une option pour laisser le code, comme dans les produits SaaS, mais si le code est mis à la disposition des clients, cela peut ne pas être une option car il peut être analysé par des concurrents. Tant de code de nos jours n'est pas compilé et même si c'est le cas, les indicateurs de définition / fonctionnalité dans le code sont du même niveau de complexité que les branches.
Jiri Klouda

-3

Je pense que les outils que vous utilisez sont un facteur important ici.

  • Si vous utilisez subversion, restez avec l'option 1 et libérez des branches.
  • Si vous utilisez GIT, l'option 2 fonctionnera bien pour vous.

2
Le branchement des fonctionnalités peut être facilement réalisé avec n'importe quel SCM
hdost
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.