Intermédiaire

Avoir une bonne stratégie avec Git Flow

Git est l’outil le plus utilisé pour versionner nos projets, c’est bien, c’est utile mais quand on commence à être plusieurs sur un même projet, les problèmes peuvent arriver très rapidement. Adopter une bonne stratégie en utilisant Git est donc de mise si nous voulons éviter tout ça. Dans cet article nous parlerons de Git Flow, une technique utilisée qui se base sur la création de branche. Nous verrons tout d’abord les principes de base avant de passer sur un cas pratique.

Pourquoi Git Flow ?

Ne vous est-il jamais arrivé de travailler en équipe sur un projet, et au moment de faire un git push, un message d’alerte vous prévient que votre version locale n’est pas à jour ? Du coup, vous faites un git pull pour vous mettre à jour afin de push mais… Catastrophe ! Git vous prévient qu’il y a un conflit. La charge de résoudre tous ces conflits vous incombe donc. Quand il ne s’agit que de quelques lignes cela peut passer, mais lorsqu’il s’agit de fichiers entiers, cela peut vite devenir fastidieux.

Pas de panique ! Git Flow est là ! Ce workflow est facile à comprendre et évite beaucoup de conflits. Il permet aussi une meilleure visibilité et gestion des releases et donc une mise en production en bonne et due forme. Normalement, Git Flow couvre l’ensemble des besoins standards pour la plupart des projets de développement. Git Flow fonctionne encore mieux si vous travaillez en suivant une méthodologie Scrum avec des sprints, comme Scrum. En effet, Git Flow fonctionne avec un système de features, c’est-à-dire que chaque nouvelle fonctionnalité à ajouter dans votre projet sera tagguée et aura sa propre branche avant d’être mergée dans la branche develop, du coup chaque user story pourra correspondre à une feature et chaque sprint à une release qui aura son propre tag de version.

Certains préfèreront utiliser Github Flow, qui est un peu la version légère de Git flow. Github Flow semble plus simple à appréhender et adapté aux déploiements en production plus récurrents : on n’attend plus d’avoir fini une release pour déployer. Il fonctionne avec 2 branches :

  • master qui est la branche principale à partir de laquelle on déploie.
  • XXX qui sera une branche tirée du master et sur laquelle on commit et ouvre des pull requests avant de merger sur le master, qui gardera un historique des pull requests.

Revenons à Git Flow. Il existe pas mal d’outils avec une interface graphique, en voici 2 principaux :

  • Source Tree fait partie de la suite Atlassian (BitBucket, Confluence, Jira, etc.) et est très utilisé par les professionnels. Il fonctionne très bien et intègre Git Flow nativement.
    • Atouts : très stable, très utilisé dans les entreprises, on peut facilement le jumeler avec les autres applications Atlassian et propose la plupart des fonctionnalités de git
    • Inconvénients : selon mon expérience, il est très gourmand en ressources, les requêtes (pull et push) ne sont pas faites en asynchrones et bloquent toute l’application pendant qu’elles s’exécutent
  • GitKraken est un nouvel outil développé par Axosoft. Il intègre aussi GitFlow. C’est ce que j’utilise et j’en suis plutôt satisfait.
    • Atouts : L’interface est très séduisante, l’application est légère et rapide, il suffit de faire un simple drag and drop pour merger deux branches.
    • Inconvénients : Cette application est encore très jeune, il lui arrive donc parfois encore de crasher.

Sinon, vous pouvez installer git-flow afin de l’utiliser dans un terminal.

Principe de base

La base de Git Flow réside dans un système de branches bien spécifique :

git-flow-schema

Non, ceci n’est pas un plan du métro. Sur le schéma, nous pouvons voir les deux branches principales :

  • master qui garde le même rôle qu’avant. C’est la branche principale qui correspond à la version stable du projet, celle qui est en production et qui porte les tags des versions.
  • develop est la branche de développement. C’est ici qu’on va tirer les branches pour travailler sur les features/releases, elle correspond à l’environnement de développement, on y prépare les changements en vue de la prochaine release dans master

ATTENTION : Il ne faut jamais travailler sur ces deux branches ! Donc pas de commit/push ici !

En plus des branches principales, vous constatez d’autres branches qui sont tirées dans tous les sens :

  • feature/xxx est tirée de la branche develop afin de travailler sur une fonctionnalité (une user story contenue dans un sprint par exemple). Une fois cette feature terminée, on la merge dans develop afin de la rendre disponible pour la prochaine release. On essaye, dans la mesure du possible, d’éviter de créer plusieurs features qui utilisent des fichiers communs en même temps afin d’éviter les conflits.
  • release/xxx est tirée de la branche develop. Elle regroupe toutes les features ajoutées depuis la dernière release (ou depuis le début du sprint) et que l’on veut mettre en production. C’est à ce moment-là que l’on fait les dernières vérifications, corrections de bugs, ajouts de fonctionnalités au dernier moment. Une fois que l’on a fini, on merge la release dans develop ET dans master en n’oubliant pas de changer le tag de la version.
  • hotfix/xxx est à utiliser en cas d’extrême urgence ! Elle est dédiée à la correction de bugs de production sur master. On la tire donc de cette dernière, une fois le bug corrigé il faudra donc merger le hotfix dans master ET dans develop (attention aux conflits)

Ces branches sont fermées une fois qu’on les a mergées et donc disparaissent de votre Git. De plus, ces branches restent généralement en local car, dans la plupart des cas, on est seul à travailler sur une feature donc il n’est pas nécessaire de faire de push une fois qu’on a fait un commit (sauf si on travaille sur plusieurs machines).

Un cas pratique

Initialiser un dépot Git

Installez Git Flow sur votre ordinateur et créez un dossier dans lequel vous ajouterez un fichier. Rendez-vous dans ce dossier avec votre terminal et tapez la commande git init pour initialiser un dépot git. Ajoutez votre fichier avec la commande git add . (avec git donc), commitez git commit -m "Mon premier commit". Automatiquement Git va créer la branche master. Pour le moment rien de nouveau, on est dans un dépot Git tout ce qui a de plus normal.

Initialiser Git Flow

Afin de pouvoir travailler avec Git Flow, il va falloir créer la branche develop tirée à partie de la branche master. Pour cela, il suffit d’exécuter la commande git flow init. Quelques questions vont vous être posées afin de déterminer le nom des branches – en principe, on laisse les noms par défaut (il suffit d’appuyer sur la touche entrée sans rien écrire). Exécutez la commande git branch et vous verrez que vous avez changé de branche pour aller sur develop.

Nouvelle feature

Créons une nouvelle feature en tapant dans notre terminal git flow feature start main (où main est le nom de notre feature). Après l’éxecution de la commande, vous verrez des indications sur ce que Git Flow a fait. Il vient de créer la branche feature/main et nous a basculé dessus.

Ajoutons un fichier index.html dans notre projet et ajoutons-y du HTML. Une fois cela fait on peut commiter : git add index.html et git commit -m "Ajout de la page principale". Si nous avons besoin de publier notre commit sur un serveur distant, nous pouvons utiliser la commande git flow feature publish main. Elle se chargera de créer la branche sur le serveur distant et de push notre commit. Afin de récupérer les données il suffit de faire un git pull sur la bonne branche comme nous en avions l’habitude avec Git.

Une fois qu’on a terminé notre feature, il suffit de taper la commande git flow feature finish main. Git Flow va donc :

  • fusionner la branche feature/main avec develop
  • supprimer la branche feature/main en local et sur notre serveur
  • nous balancer sur la branche develop.

Nouvelle release

Même principe que pour une feature, tapons la commande git flow release start v0.1 (par convention, on utilise un nom de version). A ce niveau, on peut changer le nom de la version dans nos fichiers readme.md, package.json, etc. Une fois qu’on a terminé avec nos vérifications, on fait un commit (git add puis git commit -m "Derniers correctifs") puis on termine (même principe que pour la feature) git flow release finish v0.1. Cette fois-ci, Git Flow va nous proposer de mettre un message pour le commit de la fusion avec master, une étiquette afin de taguer notre release et enfin un message pour le commit de la fusion avec develop.

Une fois tout cela validé, git flow va se charger de :

  • merger notre release avec master
  • tagger notre release (avec l’étiquette que nous avons choisie)
  • merger la release avec develop
  • supprimer la branche release/v0.1
  • nous balancer sur la branche develop

Pour publier nos modifications, il suffit de taper la commande git push --tags. N’oublions pas non plus de pusher la branche master git push origin master.

Hotfix !

Nul n’est parfait… Il peut arriver d’avoir un bug en production qu’il faut absolument corriger. Pour cela, nous devons créer un Hotfix : git flow hotfix start bug. Faisons nos corrections, commitons git add, git commit -m "Correction du bug" puis on termine git flow hotfix finish bug. Ici, tout comme dans un finish release, on nous demandera de mettre un message pour le commit de la fusion avec master, une étiquette afin de tagger notre hotfix et enfin un message pour le commit de la fusion avec develop.

Git Flow va donc :

  • merger notre hotfix avec master
  • tagger notre hotfix (avec l’étiquette que nous avons choisie)
  • merger le hotfix avec develop
  • supprimer la branche hotfix/bug
  • nous balancer sur la branche develop

Conclusion

Comme nous avons pu le voir, Git Flow nous propose une manière simple et claire d’organiser nos dépots Git, chaque opération est détaillée et une équipe peut travailler sur un même projet sans rencontrer trop de conflits. Cependant il faut savoir que l’historique généré par un tel workflow est assez chaotique visuellement parlant, les branches sont tirées de tous les côtés, mais cela ne reste qu’un problème cosmétique, de plus certaines interfaces graphiques permettent d’avoir un rendu meilleur.

Nous avons pu constater que Git Flow correspond parfaitement aux méthodologies comme Scrum. Chaque feature correspond à une user story et chaque release à un sprint. Par contre, si vous souhaitez pouvoir déployer en production plusieurs fois par jour, il n’est pas conseillé d’utiliser ce workflow, je vous conseillerais de vous tourner plutôt vers Github Flow.

© SOAT
Toute reproduction interdite sans autorisation de l’auteur

Pour aller plus loin

Nombre de vue : 4520

COMMENTAIRES 6 commentaires

  1. Nathan dit :

    Hello !
    Super article 🙂
    juste une question : Pourquoi ce workflow est déconseillé pour publier plusieurs fois par jour ? Surtout que vous présentez un outil qui simplifie à l’extrême ces manipulations.

  2. Nicolas GARIN dit :

    Salut !

    Merci pour le compliment 🙂

    Disons que j’ai voulu mettre en avant GitHub Flow qui propose approche beaucoup plus simplifiée pour les déploiements plus récurrents. Si on veut travailler en méthode agile on attendra plutôt la fin du sprint avant de déployer en production. Mais sinon rien ne l’empêche ;).

  3. Grégoire Quentin dit :

    Quelques remarques au passage :
    • ton schéma peut laisser penser que les branches de feature sont éternelles, et réutilisées (bref le schéma fait plus penser à des branches allouées à une “ressources humaine”)
    • “en méthode agile on attendra plutôt la fin du sprint”, là tu parles de Scrum, en Kanban par exemple les Sprints n’existent pas ;o)
    • du coup, tu es plus merge que rebase ?

  4. Nicolas GARIN dit :

    Salut Gregoire,

    Merci pour tes remarques, je vais faire quelques corrections 🙂

    Pour le moment je suis plutôt merge, mais j’avoue que je ne me suis pas vraiment posé sur le sujet pour prendre une décision. Apparemment on a un historique plus propre en faisant du rebase

  5. […] Lire la suite dans l’article original. […]

  6. Sacquet dit :

    Bonjour

    Je suis bien d’accord qu’il faut distinguer le mode DevOps et le mode Palier construit autour de release majeurs basées sur des intégrations planifiées de release.
    Mais le modele gitflow implémenté partout comme tu le décrit reste ambigu car il hésite entre le mode Palier et le mode continu DevOps. Dans le mode Palier avec disons une release mensuelle pour plusieurs équipes ou en tout cas plusieurs développeurs, la période de mise au point, c’est à dire de fusion intégration de la release donne lieu comme indiqué à du dev et de l’intégration continu pour cette release. En même temps, comme c’est juste de la mise au point finale, les équipes ont déjà entamé l’intégration continu pour la release du mois suivant. Or ce mode Palier de développement et d’intégration en parallèle n’est pas possible avec ce schéma de mise en oeuvre de Gît, qui n’est pas non plus adapté à DevOps. Il faut créer une branche d’intégration par projet de release et montrer sur le dessin qu’elle s’interrompt. Comme les branches de features. C’est la remarque de Grégoire.
    L’autre grand risque est que les branches de features s’éternisent créant de forte dette d’intégration sans respect du Time boxing du sprint.
    J’ai essayé d’aborder ces sujets éternels dans mon bouquin “mettre en oeuvre DevOps” si ces questions vous intéressent.
    Bon dev
    Alain

AJOUTER UN COMMENTAIRE