Si vous êtes en train de lire cet article, c’est que vous souhaitez améliorer vos process Git afin d’utiliser toute la performance de l’outil. Vous êtes au bon endroit !

Objectifs

A la fin de cet article, vous saurez :

  • Faciliter la gestion des développements par votre équipe avec une gestion de branche par ticket
  • Corriger rapidement un bug critique en production
  • Améliorer la visibilité et le suivi d’avancement pour votre gestion de projets
  • Mettre en place une nomenclature pour augmenter la lisibilité du code produit pour vos fonctionnalités

Bonne lecture !

Avant de démarrer

Cet article traite de Git d’un point de vue professionnel pour ceux qui utilisent Git uniquement comme un outil de sauvegarde de fichiers.

Les process présentés peuvent être améliorés lorsque vous prendrez de l’expérience sur la gestion des branches et la mise en place de tests automatiques/pipelines.

Ce document n’est pas la vérité absolue, simplement une des manières d’utiliser Git en entreprise !

Il s’agit des process que je mets généralement en place chez mes clients. Il n’existe pas de process Git parfait, à vous de l’adapter à votre fonctionnement interne. Rien qu’à voir, l’utilisation de Git n’est pas la même chez BitBucket que chez GitHub !

Il est conseillé d’avoir au moins 2 environnements, un de tests et un de production, pour avoir ce process Git. Dans le cas inverse, vous risquez juste d’alourdir votre gestion de projet. Je tiens à préciser qu’avoir 1 seul environnement n’est vraiment pas conseillé pour des projets de développement qui ont pour vocation d’être utilisés à des fins professionnelles.

Nous verrons ensemble des bonnes pratiques de Git pour augmenter la performance d’utilisation dans votre quotidien pour utiliser Git comme un allié et non comme un outil lambda.

Mais pour ça, il faut d’abord maîtriser certaines notions avant de continuer la lecture.

Vous devez notamment connaître les commandes de bases :

  • Commit ses modifications : git commit, git add …
  • Création de branche : git branch BRANCHE, git checkout -b NEWBRANCHE OLDBRANCHE
  • Envoyer/récupérer les informations : git push, git pull, git fetch

Toute votre équipe doit être prête à mettre en pratique et à respecter ces nouvelles pratiques, et plus spécifiquement les nomenclatures qui seront mises en place.

Enfin, vous devez obligatoirement gérer vos développements sous forme de tickets ou de user stories afin de pouvoir découper les étapes de votre projet.

Gestion des branches

Utilisation standard de Git

Pour commencer, prenons une utilisation “standard” de Git dans une équipe de développeur qui est composée des branches suivantes :

  • Master
  • Develop
  • Une branche de développement par développeur
Gestion du process avec une branche par développeur

Chacun développeur possède sa branche de développement, qu’il merge dans la “develop” une fois que ses développements sont terminés.

Une fois la version “develop” testée, elle est fusionnée dans la branche “master” pour obtenir la dernière version stable mise en production.

Cette utilisation de Git permet de gérer les cas standards, c’est à dire lorsque les développements se déroulent bien, que le code produit n’a aucune erreur et que les tickets sont gérés un à un de bout en bout sans interruption.

Quels sont les inconvénients ?

  • Il est impossible de corriger directement en production en cas de problèmes sans ajouter les développements en cours de la “develop”
  • Les merge conflits se retrouvent sur la branche de développement, c’est à dire que tous les développeurs sont impactés
  • Il est impossible de gérer en parallèle plusieurs fonctionnalités différentes de manière indépendante

Faciliter l’utilisation de Git

Il est possible de corriger tous ces problèmes en modifiant votre utilisation de Git avec ce fonctionnement : (oui ça fait peur, mais c’est pour votre bien !)

Process git final

Nous allons dans un premier temps voir les différents types de branches, et ensuite le fonctionnement.

Notion très importe, plus aucun merge ne sera fait directement ! Nous allons utiliser uniquement des pulls requests, que nous verrons ensemble plus bas dans l’article.

Vous allez avoir une multitude de types de branches dont les principales :

  • master : (unique) branche contenant le code en production
  • develop : (unique) branche contenant le code en développement

La branche de “develop” devient maintenant la branche de référence pour les développements. Il contient l’intégralité du code de la branche “master” + les dernières fonctionnalités qui seront à mettre en production à la prochaine release.

Les types de branches

Les branches de développements

Une fonctionnalité est une branche qui est toujours créée à partir de la branche de “develop”.

Pourquoi ?

Car une fonctionnalité apporte une nouveauté au code. Elle doit donc être développée, testée puis ensuite déployée sur la production.

Voici une liste non exhaustives des principaux types branches :

  • feature : nouvelle fonctionnalité
  • chore : nettoyage du code source, gestion des dépendances (sans modification du code)
  • experiment : expérimentation de fonctionnalités
  • bugfix : modification à apporter sur la “develop” pour les bugs non critiques

Il est tout à faire possible d’ajouter des types de branches en fonction des besoins de votre équipe.

git checkout develop
git checkout -b NOMDELABRANCHE // ex : feature/251-ajout_du_mockup

Une fois le développement testé, il peut ensuite être mergé sur la branche “develop” pour intégrer les fonctionnalités à ajouter dans la prochaine release.

La branche de correction critique

Dans un monde idéal, aucun bug critique ne serait déployé en production. Hors, ce type de cas peut arriver, et Git nous permet de rapidement intervenir sur les dysfonctionnements en production.

  • hotfix : modification à apporter sur la production pour les bugs critiques

Très important, les branches “hotfix” sont les seules que l’on crée à partir de la branche “master”.

git checkout master
git checkout -b NOMDELABRANCHE // ex : hotfix/134-erreur_500_formulaire_contact

Il est impossible de les créer à partir de la “develop”, car au moment du merge, tous les nouveaux développements seront aussi ajoutés sur la production, c’est que l’on ne souhaite ABSOLUMENT PAS faire.

Une fois la branche “hotfix” mergé sur la branche “master”, il faut aussi bien penser à la merger sur la branche “develop” sinon cette modification sera perdue à la prochaine release.

Les branches release

Et la branche “release” dans tout ça ?

  • release : version à tester avant la mise en production

Lorsque vous êtes satisfaits de votre branche développement et que vous souhaitez la livrer en production, vous allez d’abord la tester en créant une nouvelle branche “release”.

Cette nouvelle branche release doit contenir un nouveau numéro de version.

git checkout develop
git checkout -b release/VERSION

Pourquoi ?

Pour permettre aux développeurs de continuer à développer des nouvelles fonctionnalités sur la branche “develop” le temps que la branche “release” soit totalement testée avant d’être livré sur la “master”.

Une fois livrée sur la “master”, on crée un nouveau tag sur la master contenant le numéro de version, et surtout, on déploie la “release” sur la “develop”. Il s’agit de la même chose que pour les branches “hotfix”, il faut propager les corrections sur l’environnement de développement pour ne pas les perdre.

Pour conclure

Le process implique que la branche “develop” contienne en permanence l’intégralité de la branche “master” + les nouvelles fonctionnalités. Si un développement se trouve uniquement sur la “master”, il sera impossible de valider les tests car le code ne sera pas iso sur les deux environnements.

Pour terminer, il faut impérativement ajouter un nouveau tag sur la branche “master”, pour spécifier qu’il s’agit d’un nouvelle version, celle contenant le code actuel de production + le correctif.

Les tags

Un tag sur une branche permet de spécifier un numéro de version. A chaque nouveau merge sur la branche “master”, il faut attribuer un nouveau tag contenant la version, ce qui permettra d’avoir un historique des versions déployées.

git checkout master
git tag VERSION // ex : git tag 1.2.0

Pourquoi ?

En cas de déploiement “foireux” en production (car oui, ça vous arrivera), vous pourrez rapidement revenir à une version antérieure !

La nomenclature

C’est à cette étape que la découpe du projets en ticket prend toute son importance.

Fini les branches par développeurs. Chaque nouvelle branche sera associé à un numéro de ticket, pour faire le lien entre l’outil de gestion de projets et l’architecture des branches Git.

Pourquoi ?

A chaque branche merge sur la “develop”, le ticket peut être fermé et la tâche cloturée sur le suivi de projet. La boucle est bouclée !

La nomenclaure est la suivante : TYPEDEBRANCHE/IDTICKET-DESCRIPTION_DU_TICKET

  • Le type de branche : feature, experiment…
  • L’ID du ticket, pas obligatoire s’il s’agit de faire des expérimentations en dehors du planning
  • La description du ticket, 50 caractères maximum, qui commence par un tiret avec des underscores entre les mots

Ce qui donne les exemples :

  • feature/221-create_mockup_api
  • experiment/try_implements_pipelines_gitlab
  • hotfix/389-contact_form_disappear

Rassembler les développements

L’intérêt d’avoir une branche par tâche, c’est qu’il est maintenant possible de changer de développeurs sur un ticket, sans que celui-ci soit déployé sur la branche “develop”.

Expliciter ses commits

La règle d’or d’une bonne utilisation de Git est d’être capable de créer un historique. Il ne s’agit pas de commit la moindre modification, mais plutôt de s’organiser pour diviser sa tâche en plusieurs sous tâches indépendantes.

Au lieu de faire un commit pour une fonctionnalité entière, il est intéressant de commit par groupement de développements. Pour être certain que vous commits sont bons, il faut que vous soyez capable de comprendre exactement ce que contiennent vos commits en quelques mots.

git add FILES
git commit -m "MESSAGE"

Quelque exemples :

  • La création de nouvelles tables en base de données
  • Mise en place de la modification de l’espace client en back-end, et un 2e commit pour la modification en front

Pourquoi ?

Plus votre commit contient de modification, plus il sera difficile de comprendre les modifications faites.

La nomenclature

La nomenclaure est la suivante : TYPEDECOMMIT(SCOPE): DESCRIPTION

  • Le type de commit : feat, docs, refactor, perf…
  • Le scope entre parenthèses pour préciser un contexte
  • La description brève du ticket

Ce qui donne les exemples :

  • feat: add italian as new language
  • refactor(user): add comments on all users’ functions
  • docs: correct spelling of CHANGELOG

Si vous voulez aller plus loin dans la nomenclature, référez vous sur les Conventional Commits, voici le lien

Pull requests

Intérêt d’une pull request

Une pull request consiste à faire valider l’intégralité du code de ses commits avant de les merge sur une nouvelle branche.

Mais quel est l’intérêt de faire ça ?

Il y a trois points principaux.

Le premier consiste aux développeurs d’être tenu au courant des modifications faites par les autres. Vous pouvez mentionner d’autres membres de votre équipe avant de faire un merge pour les notifier que la branche commune “develop” possède maintenant une nouvelle fonctionnalité. Ils pourront alors se tenir au courant des développements, sans plus avoir de surprise.

Le deuxième, et le plus important, consiste à avoir un suivi des développements, ainsi qu’un historique. En attribuant vos pull requests à vos tickets, vous pourrez directement voir les modifications apportées pour chacune des tâches. Plus besoin de se demander à quel moment vous avez modifié tel ou tel paramètre, vous n’avez plus qu’à vous référer à votre ticket.

Cette intégration est très facile avec des outils comme Jira ou Azure Devops. Si votre outil de suivi de tickets ne contient pas de connexion directe avec Git, vous pourrez dans tous les cas chercher vos modifications directement dans les PR.

Le troisième consiste à ne plus avoir de conflits lors des merges. En utilisant une PR plutôt qu’un merge à la main, il vous sera impossible d’avoir des conflits car Git refusera automatiquement la PR, ce qui vous permet de ne pas push du code qui ne fonctionne pas !

Un quatrième avantage, à mettre en place uniquement dans les équipes de développement conséquentes, consiste à ce que les autres développeurs du projet puisse comprendre le code contenu dans le merge pour le valider à leur tour. Avec cette étape, chacun peut vérifier les bonnes pratiques de code : nomenclature des variables, contenu des commentaires, complexité des fonctions… Attention à ne pas introduire de problème d’égo dans ce process. Il ne s’agit pas ici de montrer qui est le meilleur ! L’ensemble de l’équipe doit prendre les PR comme une opportunité de devenir de meilleurs développeurs et de diminuer ensemble la complexité de l’application.

Fonctionnement d’une pull request

A partir de maintenant, votre équipe ne devra plus jamais faire de merge directement sur la branche “develop”, c’est les PR qui le feront pour vous.

Une fois que tes développements sont terminés sur une branche, il faut récupérer l’intégralité des changements pour vérifier s’il n’y a pas de conflits entre la branche en cours et “develop”.

Les étapes sont les suivantes :

  • Fetch la branche de destination
  • Pull la branche de destination sur la branche de destination
  • Merge la branche de destination sur sa branche
  • Résoudre les conflits s’il y en a
  • Commit les changements
  • Créer une Pull Request
git fetch
git checkout MABRANCHEFEATURE
git pull develop
git add .
git commit -m "MESSAGE"
git push

Ces étapes peuvent vous sembler lourdes, mais elles vous permettent d’avoir toujours des environnements identiques.

Prenons un exemple pour le prouver avec 2 développeurs (Alex et Pauline) qui travaillent ensemble sur la réalisation de fonctionnalités.

  • Alex et Pauline créent chacun une branche à partir de la “develop” (B1 pour Alex et B2 pour Pauline)
  • Pauline finit ses développements et fait une PR de la branche B2 vers la “develop”
  • La PR est acceptée et mergée
  • Alex finit ses développements et souhaite faire une PR de la branche B1 vers la “develop”

Ici, vous avez un problème. Avez-vous trouvé ?

La branche “develop” à partir de laquelle Alex a crée sa branche B1 n’a plus le même contenu que celle actuelle. Elle contient en plus la fonctionnalité de Pauline.

Il faut impérativement qu’Alex récupère d’abord le nouveau contenu de la branche “develop” et qu’il la merge en interne dans sa branche B1 pour être sûr qu’il n’y aura pas de conflits et revalider ses tests. Si tout est bon, il peut ensuite créer une PR.

Voyez la branche “develop” comme une branche incrémentale qu’il faut toujours merger dans notre branche “feature” avant de faire une PR. C’est OBLIGATOIRE (si vous ne voulez pas avoir de régression).

Pour créer une PR, il vous suffit d’aller sur votre outil Git en ligne et en créer une.

L’interface permet de mettre un message clair sur le contenu de la PR, d’y ajouter des commentaires, des observateurs, des labels etc… Soyez le plus précis possible pour faciliter la lecture par vos collaborateurs !

Exemple de PR de la “develop” vers la “master”

La PR contient l’intégralité des modifications entre la branche de départ et celle de destination. En un coup d’oeil, vous pouvez valider les fichiers ajoutés/modifiés/supprimés avec les changements pour chacun d’entre eux.

Contenu d’une PR (ensemble de fichiers modifiés dans les commits)

Vous pouvez évidemment rejeter une Pull Request lorsque celle-ci ne respecte pas suffisamment votre process : tests imparfaits, manque de commentaires, mauvaise nomenclature…

2 choix s’offrent à vous :

  • Soit la PR nécessite une petite modification. Elle est mise en attente le temps que la branche que de nouveaux commits soient faits. Une PR prend automatiquement en compte tous les prochains commits faits sur la branche de départ
  • Soit la PR est défectueuse. Elle est annulée et une nouvelle PR sera faite lorsque le code sera améliorée

Dans tous les cas, le code ne sera pas envoyé vers la branche de destination tant que la PR ne sera pas validée et mergée.

Sécurité

Maintenant que vous avez en place les PR, il n’est plus question de faire des merges directement sur vos branches “develop” et “master”.

Il est conseillé de bloquer les merges via la configuration de votre outil Git. De cette manière, plus aucune personne de l’équipe pourra merge une branche sans passer par une PR.

Blocage des merges sur GitHub

L’intérêt est d’autant plus important sur la branche “master”. C’est déjà arrivé à presque tous les développeurs de se tromper de branche lors d’un merge. Il sera maintenant impossible de faire l’erreur !

L’autre point très important, c’est l’ajout d’approbation. Vous pouvez définir un nombre d’approbateur qui doivent valider la PR pour qu’ils puissent être mergés sur la branche de destination. Dans le cas de la production, vous pouvez définir que le chef de projet ainsi que 3 développeurs doivent accepter le code pour qu’il soit passer sur la branche “master”, très intéressant pour les corrections critiques en production.

Aller plus loin

Maintenant que vous savez comment mettre en place un process Git digne des plus grands (cf : comme chez Atlassian), vous allez pouvoir poursuivre en allant plus loin.

Une fois que vous maitrisez Git, vous pourrez ensuite vous attaquer au(x) :

  • Déploiement continu CI/CD
  • Tests automatiques avant les merges