Le flux Git amélioré expliqué
Publié: 2022-03-11Causer des dommages par inadvertance avec Git peut être trop facile. Pourtant, la meilleure façon d'utiliser Git sera toujours controversée.
C'est parce que Git lui-même ne détaille que les opérations de branchement de base, ce qui laisse ses modèles d'utilisation, c'est-à-dire les modèles de branchement, une question d'opinion de l'utilisateur. Les modèles de branchement Git promettent de soulager la douleur en organisant le chaos qui survient inévitablement lorsque les développeurs de logiciels apportent des modifications à leurs bases de code.
Comme de nombreux développeurs, vous vouliez quelque chose qui "fonctionnerait simplement" pour que vous puissiez vous consacrer au développement de logiciels. Vous avez donc choisi Git flow , un modèle de branchement souvent recommandé aux utilisateurs de Git. Peut-être étiez-vous d'accord avec la logique de Git flow au début, jusqu'à ce que vous rencontriez des problèmes avec lui dans la pratique. Ou peut-être que Git flow ne vous semble pas assez adapté pour que vous l'adoptiez. Après tout, il y a d'innombrables variables en jeu, et aucun modèle de branchement unique ne fonctionnera bien dans toutes les situations.
Bonnes nouvelles! Variante du modèle de flux Git classique, le flux Git amélioré simplifie les manœuvres les plus courantes du flux de travail Git tout en conservant les principaux avantages.
La splendeur et la misère du modèle de flux Git classique
Je suis un ardent défenseur du flux Git depuis que j'ai découvert à quel point il excelle lors du développement d'un produit qui évolue par incréments de valeur significatifs (en d'autres termes, des versions ).
Un incrément de valeur significatif nécessite un temps considérable, comme les sprints de plus de deux semaines généralement utilisés dans le développement basé sur Scrum. Si une équipe de développement s'est déjà déployée en production, il peut y avoir des problèmes si la portée de la prochaine version s'accumule au même endroit où réside le code de production, par exemple, dans la branche principale du dépôt Git qu'elle utilise.
Alors que le produit est encore dans la phase de développement initiale, c'est-à-dire qu'il n'y a pas de production et qu'il n'y a pas de véritables utilisateurs du produit, l'équipe peut simplement tout garder à l'intérieur de la branche principale. En fait, c'est plus que correct : cette stratégie permet le rythme de développement le plus rapide sans trop de cérémonie. Mais les choses changent dans un environnement de production ; ensuite, de vraies personnes commencent à compter sur le produit pour être stable.
Par exemple, s'il y a un bogue critique en production qui doit être corrigé immédiatement, ce serait un désastre majeur pour l'équipe de développement de devoir annuler tout le travail accumulé dans la branche principale jusqu'à présent juste pour déployer le correctif. Et déployer du code sans tests appropriés, que le code soit considéré comme à moitié ou bien développé, n'est clairement pas une option.
C'est là que les modèles de branchement brillent, y compris le flux Git. Tout modèle de branchement sophistiqué devrait répondre aux questions concernant la façon d' isoler la prochaine version de la version du système actuellement utilisée par les utilisateurs, comment mettre à jour cette version avec la prochaine version et comment introduire des correctifs de bogues critiques dans la version actuelle.
Le processus de flux Git répond à ces scénarios fondamentaux en séparant "main" (la branche de production ou "version actuelle") et "develop" (la branche de développement ou "prochaine version") et en fournissant toutes les règles d'utilisation des branches feature/release/hotfix . Il résout efficacement de nombreux maux de tête liés aux workflows de développement de produits basés sur des versions.
Mais même avec des projets bien adaptés au modèle de flux Git classique, j'ai subi les problèmes typiques qu'il peut apporter :
- Le flux Git est complexe, avec deux branches à longue durée de vie, trois types de branches temporaires et des règles strictes sur la façon dont les branches traitent les unes avec les autres. Une telle complexité rend les erreurs plus probables et augmente l'effort nécessaire pour les corriger.
- Les branches release et hotfix nécessitent une "double fusion" - une fois dans main, puis dans develop. Parfois, vous pouvez oublier de faire les deux. Vous pouvez faciliter la création de branches de flux Git avec des scripts ou des plugins client VCS GUI, mais vous devez d'abord les configurer pour chaque machine de chaque développeur impliqué dans un projet donné.
- Dans les flux de travail CI/CD, vous vous retrouvez généralement avec deux versions finales pour une version : une provenant du dernier commit de la branche de version elle-même et une autre du commit de fusion vers main. À proprement parler, vous devriez utiliser celui du principal, mais les deux sont généralement identiques, ce qui crée un risque de confusion.
Entrez "Flux Git amélioré"
La première fois que j'ai utilisé le flux Git amélioré, c'était sur un nouveau projet à code source fermé. Je travaillais avec un autre développeur, et nous avions travaillé sur le projet en nous engageant directement sur la branche principale.
Remarque : jusqu'à la première version publique d'un produit, il est tout à fait logique de valider toutes les modifications directement dans la branche principale, même si vous êtes un partisan du flux Git, pour des raisons de rapidité et de simplicité du workflow de développement. Puisqu'il n'y a pas encore de production, il n'y a aucune possibilité de bogue de production que l'équipe doive corriger dès que possible. Faire toute la magie de branchement que le flux Git classique implique est donc exagéré à ce stade.
Ensuite, nous nous sommes rapprochés de la version initiale et nous avons convenu qu'au-delà de ce point, nous ne serions plus à l'aise de nous engager directement dans la branche principale. Nous avions évolué assez rapidement et les priorités commerciales ne laissaient pas beaucoup de place pour établir un processus de développement solide comme le roc, c'est-à-dire un processus avec suffisamment de tests automatisés pour nous donner l'assurance que notre branche principale était prête à être publiée.
Cela semblait être un cas valable pour le modèle de flux Git classique. Avec des branches principales et développées séparées et suffisamment de temps entre les incréments de valeur significatifs, il y avait confiance que la plupart des QA manuelles donneraient des résultats assez bons. Lorsque j'ai plaidé pour le flux Git, mon collègue a suggéré quelque chose de similaire, mais avec quelques différences clés.
Au début, j'ai repoussé. Il m'a semblé que certains des "correctifs" proposés au flux Git classique étaient un peu trop révolutionnaires. Je pensais qu'ils pourraient casser l'idée principale et que toute l'approche échouerait. Mais en y réfléchissant davantage, j'ai réalisé que ces ajustements ne brisaient pas réellement le flux Git. Pendant ce temps, ils en font un meilleur modèle de branchement Git en résolvant tous les points douloureux mentionnés ci-dessus.
Après avoir réussi avec l'approche modifiée dans ce projet, je l'ai utilisée dans un autre projet à source fermée avec une petite équipe derrière, où j'étais le propriétaire permanent de la base de code et un développeur externalisé ou deux aidés de temps en temps. Sur ce projet, nous sommes passés en production six mois plus tard, et depuis lors, nous utilisons les tests CI et E2E depuis plus d'un an, avec des versions tous les mois environ.
Mon expérience globale avec cette nouvelle approche de création de branches a été si positive que j'ai voulu la partager avec mes collègues développeurs pour les aider à contourner les inconvénients du flux Git classique.
Similitudes avec le flux Git classique : isolation du développement
Pour l'isolation du travail dans le flux Git amélioré, il existe encore deux branches de longue durée, main et develop. (Les utilisateurs ont toujours des capacités de correctif et de version, en mettant l'accent sur les «capacités», car ce ne sont plus des branches. Nous entrerons dans les détails dans la section des différences.)
Il n'y a pas de schéma de nommage officiel pour les branches de fonctionnalités de flux Git classiques. Vous venez de vous déconnecter du développement et de fusionner pour développer lorsque la fonctionnalité est prête. Les équipes peuvent utiliser la convention de dénomination de leur choix ou simplement espérer que les développeurs utiliseront des noms plus descriptifs que "ma-branche". Il en va de même pour le flux Git amélioré.
Toutes les fonctionnalités accumulées dans la branche de développement jusqu'à un point limite façonneront la nouvelle version.
Fusions de squash
J'ai fortement recommandé d'utiliser la fusion de squash pour les branches de fonctionnalités afin de conserver un historique agréable et linéaire la plupart du temps. Sans cela, les graphiques de validation (à partir des outils GUI ou de git log --graph
) commencent à paraître bâclés lorsqu'une équipe jongle même avec une poignée de branches de fonctionnalités :
Mais même si vous êtes d'accord avec les visuels de ce scénario, il y a une autre raison d'écraser. Sans écraser, les vues d'historique de validation - parmi lesquelles git log
(sans --graph
) et aussi GitHub - racontent des histoires plutôt incohérentes, même avec les scénarios de fusion les plus simples :
La mise en garde concernant l'utilisation de la fusion de squash est que l'historique de la branche de fonctionnalité d'origine est perdu. Mais cette mise en garde ne s'applique même pas si vous utilisez GitHub, par exemple, qui expose l'historique complet d'origine d'une branche de fonctionnalité via la demande d'extraction fusionnée, même après la suppression de la branche de fonctionnalité elle-même.
Différences avec le flux Git classique : versions et correctifs
Passons en revue le cycle de publication car (espérons-le) c'est la principale chose que vous ferez. Lorsque nous arrivons au point où nous aimerions publier ce qui est accumulé dans le développement, c'est strictement un sur-ensemble de main. Après cela, c'est là que commencent les plus grandes différences entre le flux Git classique et amélioré.

Versions dans le flux Git amélioré
Chaque étape de la création d'une version avec un flux Git amélioré diffère du processus de flux Git classique :
- Les versions sont basées sur le principal, plutôt que sur le développement. Étiquetez la pointe actuelle de la branche principale avec quelque chose de significatif. J'ai adopté des balises basées sur la date actuelle au format ISO 8601 précédée d'un « v », par exemple, v2020-09-09 .
- S'il arrivait qu'il y ait plusieurs versions dans une journée, par exemple des correctifs, le format pourrait avoir un numéro séquentiel ou une lettre collée dessus selon les besoins.
- Sachez que les balises ne correspondent pas, en général, aux dates de sortie. Ils sont uniquement destinés à forcer Git à conserver une référence à l'apparence de la branche principale au moment où le processus de publication suivant a commencé.
- Poussez la balise à l'aide de
git push origin <the new tag name>
. - Après cela, une petite surprise : supprimez votre branche principale locale . Ne vous inquiétez pas, car nous allons le restaurer sous peu.
- Tous les commits sur main sont toujours sûrs - nous les avons protégés de la récupération de place en marquant main à l'étape précédente. Chacun de ces commits, même les correctifs, comme nous le verrons bientôt, fait également partie du développement.
- Assurez-vous simplement qu'une seule personne dans une équipe le fait pour une version donnée ; c'est le soi-disant rôle de "gestionnaire de publication". Un responsable de publication est généralement le membre de l'équipe le plus expérimenté et/ou le plus expérimenté, mais une équipe serait avisée d'éviter qu'un membre particulier de l'équipe n'assume ce rôle de manière permanente. Il est plus logique de diffuser les connaissances au sein de l'équipe pour augmenter le fameux facteur de bus.
- Créez une nouvelle branche principale locale au tip commit de votre branche develop .
- Poussez cette nouvelle structure à l'aide de
git push --force
, car le dépôt distant n'acceptera pas si facilement un tel "changement radical". Encore une fois, ce n'est pas aussi dangereux que cela puisse paraître dans ce contexte parce que :- Nous déplaçons simplement le pointeur de la branche principale d'un commit à un autre.
- Un seul membre de l'équipe effectue ce changement à la fois.
- Le travail de développement quotidien se déroule sur la branche develop, donc vous ne perturberez le travail de personne en déplaçant main de cette façon.
- Vous avez votre nouvelle version ! Déployez-le dans l'environnement intermédiaire et testez-le. (Nous discuterons des modèles CI/CD pratiques ci-dessous.) Tous les correctifs vont directement à la branche principale, et cela commencera à diverger de la branche de développement à cause de cela.
- Dans le même temps, vous pouvez commencer à travailler sur une nouvelle version dans la branche develop, le même avantage vu dans le flux Git classique.
- Dans le cas malheureux où un correctif est nécessaire pour ce qui est actuellement en production (pas la prochaine version en staging) à ce stade, il y a plus de détails sur ce scénario dans "Gestion des correctifs lors d'une version active..." ci-dessous.
- Lorsque votre nouvelle version est considérée comme suffisamment stable, déployez la version finale dans l'environnement de production et effectuez une seule fusion squash de main to develop pour récupérer tous les correctifs.
Correctifs dans Enhanced Git Flow
Les cas de correctif sont doubles. Si vous effectuez un correctif alors qu'il n'y a pas de version active , c'est-à-dire que l'équipe prépare une nouvelle version dans la branche de développement, c'est un jeu d'enfant : engagez-vous sur main, déployez vos modifications et testez-les jusqu'à ce qu'elles soient prêtes, puis déployer en production.
Comme dernière étape, sélectionnez votre commit de main à develop pour vous assurer que la prochaine version contiendra tous les correctifs. Si vous vous retrouvez avec plusieurs validations de correctifs, vous économisez des efforts, surtout si votre IDE ou un autre outil Git peut le faciliter, en créant et en appliquant un correctif au lieu de sélectionner plusieurs fois. Essayer d'écraser merge main pour développer après la version initiale est susceptible de se retrouver avec des conflits avec les progrès indépendants réalisés dans la branche de développement, donc je ne le recommande pas.
La gestion des correctifs lors d'une version active , c'est-à-dire lorsque vous forcez le push principal et que vous êtes toujours en train de préparer la nouvelle version, est la partie la plus faible du flux Git amélioré. En fonction de la durée de votre cycle de publication et de la gravité du problème que vous devez résoudre, essayez toujours d'inclure des correctifs dans la nouvelle version elle-même. C'est la manière la plus simple de procéder et cela ne perturbera en rien le flux de travail global.
Dans le cas où ce n'est pas possible - vous devez introduire un correctif rapidement et vous ne pouvez pas attendre que la nouvelle version soit prête - alors préparez-vous pour une procédure Git quelque peu complexe :
- Créez une branche - nous l'appellerons "nouvelle version", mais votre équipe peut adopter n'importe quelle convention de nommage ici - au même commit que l'astuce actuelle de main. Poussez la nouvelle version.
- Supprimez et recréez la branche principale locale lors de la validation de la balise que vous avez créée précédemment pour la version active actuelle. Forcer la poussée principale.
- Introduisez les correctifs nécessaires dans main, déployez-les dans l'environnement intermédiaire et testez. Dès que c'est prêt, déployez-le en production.
- Propager les modifications de la version principale actuelle à la nouvelle version, soit via une sélection sélective, soit via un correctif.
- Après cela, refaites la procédure de release : marquez la pointe du main actuel et poussez le tag, supprimez et recréez le main local à la pointe de la branche new-release, et forcez le push main.
- Vous n'aurez probablement pas besoin de la balise précédente, vous pouvez donc la supprimer.
- La branche de nouvelle version est désormais redondante, vous pouvez donc également la supprimer.
- Vous devriez maintenant être prêt à partir comme d'habitude avec une nouvelle version. Terminez en propageant les correctifs d'urgence du principal au développement via la sélection de cerises ou un correctif.
Avec une bonne planification, une qualité de code suffisamment élevée et une culture de développement et d'assurance qualité saine, il est peu probable que votre équipe doive utiliser cette méthode. Il était prudent de développer et de tester un tel plan d'urgence pour améliorer le flux Git, juste au cas où, mais je n'ai jamais eu besoin de l'utiliser dans la pratique.
Configuration CI/CD au-dessus du flux Git amélioré
Tous les projets ne nécessitent pas un environnement de développement dédié. Il peut être assez facile de configurer un environnement de développement local sophistiqué sur chaque machine de développeur.
Mais un environnement de développement dédié peut contribuer à une culture de développement plus saine. L'exécution de tests, la mesure de la couverture des tests et le calcul des métriques de complexité sur la branche de développement réduisent souvent le coût des erreurs en les détectant bien avant qu'elles ne se retrouvent dans la mise en scène.
J'ai trouvé certains modèles CI/CD particulièrement utiles lorsqu'ils sont combinés avec un flux Git amélioré :
- Si vous avez besoin d'un environnement de développement, configurez CI pour qu'il le construise, le teste et le déploie lors de chaque commit dans la branche develop. Fit in E2E testing ici aussi, si vous l'avez et si cela a du sens dans votre cas.
- Configurez CI pour créer, tester et déployer dans l'environnement de staging à chaque validation de la branche principale. Les tests E2E sont également très bénéfiques à ce stade.
- Il peut sembler redondant d'utiliser les tests E2E aux deux endroits, mais rappelez-vous que les correctifs ne se produiront pas en développement. Le déclenchement d'E2E sur les commits vers main testera les correctifs et les modifications quotidiennes avant leur sortie, mais également le déclenchement sur les commits à développer détectera les bogues plus tôt.
- Configurez CI de manière à permettre à votre équipe de déployer des builds de l'environnement principal vers l'environnement de production sur demande manuelle.
De tels modèles sont relativement simples, mais fournissent des machines puissantes pour prendre en charge les opérations de développement quotidiennes.
Le modèle de flux Git amélioré : améliorations et limitations possibles
Le flux Git amélioré n'est pas pour tout le monde. Il tire parti de la tactique controversée de la force poussant la branche principale, de sorte que les puristes peuvent en vouloir. D'un point de vue pratique, il n'y a rien de mal à cela, cependant.
Comme mentionné, les correctifs sont plus difficiles lors d'une version, mais toujours possibles. Avec une attention appropriée à l'AQ, à la couverture des tests, etc., cela ne devrait pas arriver trop souvent, donc de mon point de vue, c'est un compromis valable pour les avantages globaux du flux Git amélioré par rapport au flux Git classique. Je serais très intéressé de savoir comment le flux Git amélioré se comporte dans les grandes équipes et avec des projets plus complexes, où les correctifs peuvent être plus fréquents.
Mon expérience positive avec le modèle de flux Git amélioré tourne également principalement autour de projets commerciaux à source fermée. Cela peut être problématique pour un projet open source où les pull-requests sont souvent basés sur une ancienne dérivation de version de l'arborescence source. Il n'y a pas d'obstacles techniques pour résoudre ce problème, cela peut nécessiter plus d'efforts que prévu. J'accueille les commentaires des lecteurs ayant beaucoup d'expérience dans l'espace open source concernant l'applicabilité du flux Git amélioré dans de tels cas.
Remerciements particuliers au collègue de Toptal, Antoine Pham, pour son rôle clé dans le développement de l'idée derrière le flux Git amélioré.
Lectures complémentaires sur le blog Toptal Engineering :
- Développement basé sur le tronc vs Git Flow
- Workflows Git pour les pros : un bon guide Git
En tant que Microsoft Gold Partner, Toptal est votre réseau d'élite d'experts Microsoft. Constituez des équipes performantes avec les experts dont vous avez besoin, où que vous soyez et exactement quand vous en avez besoin !