Stratégie de branchement Git pour le code non publié de longue durée

15

Dans notre équipe, en plus des unités de travail individuelles (Histoires), nous avons des thèmes de travail plus longs (Epics). Plusieurs histoires font une épopée.

Traditionnellement, nous avons eu des branches de fonctionnalités pour chaque histoire, et avons fusionné celles-ci directement à maîtriser lorsqu'elles passent le contrôle qualité. Cependant, nous aimerions commencer à retarder la sortie des histoires terminées dans une épopée jusqu'à ce que l'épopée soit considérée comme "fonctionnalité terminée". Nous ne publierions ces fonctionnalités en production que lorsque Epic serait fermé. De plus, nous avons un serveur de construction nocturne - nous aimerions que toutes les histoires fermées (y compris celles qui font partie d'Epics incomplètes) soient déployées automatiquement sur ce serveur nocturne.

Y a-t-il des suggestions sur la façon de gérer notre repo pour y parvenir? J'ai envisagé d'introduire des "branches épiques", où nous fusionnions des histoires fermées à la branche épique connexe au lieu de les diriger directement vers le maître, mais mes préoccupations sont les suivantes:

  • Je m'inquiète des conflits de fusion qui peuvent survenir si les branches épiques restent ouvertes longtemps
  • Les constructions nocturnes nécessiteraient de fusionner toutes les branches épiques en une branche "nocturne". Encore une fois, des conflits de fusion peuvent survenir, et cela doit être fait automatiquement
Sitati
la source

Réponses:

23

Suggestion simple: ne faites pas ça.

les branches git ne sont pas pour les fourches à long terme du code, comme indiqué ici et https://blog.newrelic.com/2012/11/14/long-running-branches-considered-harmful/ . Les succursales sont mieux traitées comme des éléments transitoires utilisés pour organiser les validations par un développeur individuel au niveau quotidien. Donc, s'ils ont un nom qui correspond à quelque chose qu'un chef de projet (sans parler de l'utilisateur final) pourrait se soucier de vous, vous faites quelque chose de mal.

La pratique recommandée consiste à utiliser l'intégration continue avec des bascules de fonction ou une branche par abstraction pour garantir que:

  • tout le code est intégré à tout moment (au moins tous les jours, de préférence plus souvent)
  • ce qui est déployé est sous contrôle explicite.
Soru
la source
1
Je soupçonnais que cela pourrait être une réponse populaire! Mes principales préoccupations à ce sujet sont le surcoût de toujours maintenir à la fois l'implémentation `` en direct '' et `` suivante '', et cela nécessite également que le développeur travaillant sur une fonctionnalité sache d'avance pour créer des modifications en tant que nouvelles fonctionnalités parallèles au lieu de mettre à niveau (/ remplacer) le fonctionnalité existante. Je suppose que cela nécessite un changement de mentalité plus important dans l'équipe.
Sitati
Vous pouvez utiliser des branches pour développer du code, mais ne les utilisez jamais pour stocker du code. Donc, si vous n'êtes pas sûr si une tâche est un correctif de 30 minutes ou une reprise de 2 semaines, alors commencez sur une branche. Dès que vous le savez, fusionnez ou refactorisez une abstraction / bascule, puis fusionnez.
soru
@Sitati: Je viens de fusionner du code qui était dans une branche de fonctionnalité depuis quatre mois. En attendant, develnous sommes passés à CMake depuis Autotools, avons introduit Travis CI, refactorisé le code. En fin de compte, il était plus facile de comprendre la nouvelle fonctionnalité et de l'appliquer manuellement develque d'essayer de la fusionner. Nous avons également demandé à de nouveaux étudiants en Master de développer une nouvelle fonctionnalité dans une branche qu'ils ont créée lorsqu'ils ont commencé leur thèse. Après un an, ils l'ont poussé et il n'y a eu aucun effort pour le fusionner, il est donc devenu plus difficile de fusionner jour après jour.
Martin Ueding
2
Le billet de blog lié a maintenant 5 ans. Je déteste les bascules de fonctionnalités. Qu'y a-t-il de mal à créer une branche à long terme, à la fusionner régulièrement dans la branche de fonctionnalité à partir du principal et à ajouter une intégration continue à la branche de fonctionnalité à long terme?
Jason Kelley
CI est le nom d'un processus, pas d'un outil. Si vous avez plusieurs branches de fonctionnalités, elles ne seront normalement pas intégrées en continu les unes aux autres. Ce qui signifie trouver des problèmes plus tard que plus tôt.
soru
1

Je pense que c'est un problème assez courant et se résume à choisir les fonctionnalités à inclure dans une version après que les fonctionnalités ont été codées plutôt qu'avant.

par exemple.

J'ai les fonctionnalités A, B et C pour la v2 de mon produit. B et C sont liés, je ne veux pas libérer B sauf si C est également terminé.

J'ai trois développeurs qui travaillent tous en même temps sur les fonctionnalités.

J'ai un set in stone date de sortie D

B est terminé et fusionné, A est terminé et fusionné. C est retardé ... que dois-je faire?!

Je ne pense pas qu'il existe de solution technique à ce problème. Vous souhaitez publier une version non testée du produit avec uniquement la fonctionnalité A incluse. À moins que vous ne fusionniez et testiez toutes les combinaisons possibles de fonctionnalités, cela sera toujours une possibilité.

La solution est plus humaine. Vous avez manqué votre date de sortie et devez la repousser.

Ewan
la source
1

C'est un problème délicat mais auquel beaucoup de gens sont confrontés. Je préfère utiliser la configuration Gitflow comme point de départ.

Développement -> De nouvelles choses en cours de développement
Master -> Trucs finis nécessitant des tests Production -> Trucs qui ont été publiés en production.

Pour les fonctionnalités mineures (plus courtes), je crée une branche à partir du développement, je fais le travail, puis je fusionne la branche au développement.

Pour les fonctionnalités principales (à long terme), je crée une branche à partir du développement, je crée des branches plus petites à partir de cette branche, puis je fusionne de nouveau avec la première branche. Une fois que la fonctionnalité principale est terminée, elle revient dans la branche de développement.

À intervalles réguliers (selon le projet), je fusionne à nouveau le développement dans le maître et un cycle de test commence. Si des correctifs apparaissent lors des tests, ils sont effectués dans la branche principale (sous-branche puis fusionnez). Et le développement peut continuer sur la branche principale pendant les tests.

À tout moment, le maître doit être fusionné avec le développement, et le développement doit être fusionné avec l'une de ses sous-branches à long terme.

le maître doit toujours (en théorie) être prêt pour la production. Le développement doit toujours (en théorie) être prêt pour la production. La seule raison pour laquelle il existe une différence est de fournir un ensemble solide de fonctionnalités aux testeurs.

Une fois prêt, une validation dans le maître qui est testée est fusionnée dans la production et le déploiement en production se produit à partir de cette branche. Les HOTFIX qui doivent être effectués en cas d'urgence peuvent alors avoir lieu sur la branche Production sans avoir à fusionner dans le maître (qui peut avoir de nombreuses modifications non testées).

Mon arbre normal ressemble

 LongTerm -> Development -> Master -> Production    
 LongTerm <- Development      |            |  
     |       Development -> Master         |  
 LongTerm <- Development -> Master         |  
             Development <- Master         |  
                            Master -> Production  

C'est ma règle générale qu'aucun changement ne devrait prendre plus de quelques heures. Si c'est le cas, il doit être transformé en changements plus petits. Si c'est une fonctionnalité énorme (comme une réécriture d'interface utilisateur), cela se poursuit à long terme afin que le développement normal puisse se poursuivre en même temps. Les succursales LongTerm ne sont normalement que des succursales locales tandis que Développement, Maître et Production sont des succursales distantes. Toutes les sous-branches sont également locales uniquement. Cela garde le référentiel propre pour les autres, sans perdre l'utilité de git sur un ensemble de fonctionnalités à long terme.

Je voudrais cependant noter que l'existence d'une succursale à long terme est une chose rare. Normalement, tout mon travail est en développement. Ce n'est que lorsque j'ai une fonctionnalité (ensemble) qui va prendre si longtemps que je dois aussi pouvoir travailler sur des trucs de développement normaux que j'utilise la branche LongTerm. Si ce n'est qu'un ensemble de changements qui devraient être ensemble, je ne fusionne tout simplement pas jusqu'à ce que tout soit fait.

coteyr
la source
"Pour les fonctionnalités majeures (à long terme), je crée une branche à partir du développement" - ne devriez-vous pas créer de nouvelles branches (développement) à partir de la branche Production? Voir que la branche Production est un code prêt à être publié.
robotron
Non, la production est déjà lancée, le maître est en avance sur la production et le développement est en avance sur le maître. Une nouvelle fonctionnalité telle que l'ajout de taxe aux totaux de commande est inutile si vous ne travaillez pas sur du code qui a déjà des commandes.
coteyr
Mais si vous vous branchez à partir de dev et fusionnez plus tard, cette branche (et par conséquent master et Production plus tard) incorporera-t-elle alors tous les changements de dev effectués par d'autres jusqu'au point de se ramifier? Certaines de ces modifications peuvent ne pas être approuvées par l'AQ. Peut-être parlions-nous de différentes approches de la gestion des versions.
robotron
Oui, c'est ça le point. Les tests de QA sur un SHA spécifique dans le maître, mais vous ne pouvez pas tenir le dev pour ça.
coteyr
"QA teste sur un SHA spécifique dans le maître" -> QA teste chaque nouvelle fonctionnalité en tant que autonome? Permettez-moi d'exécuter par vous un scénario typique auquel mon équipe est confrontée: supposons que vous ayez 2 projets de longue durée sur la même base de code: le projet A est en QA pour le mois dernier et le sera pour un autre mois. Le projet B était en développement depuis 6 mois et est maintenant prêt pour l'AQ. Le projet A est fusionné en maître et n'est certainement pas prêt pour la production en raison de nombreuses erreurs subtiles de règles métier. Comment gérons-nous le projet B? A et B doivent être testés ensemble pour vérifier les interactions (B ne causera pas de conflits lors de la fusion).
robotron