Comparaison des workflows Git : ce que vous devriez savoir
Git est le système de contrôle de version le plus couramment utilisé aujourd'hui. Un workflow Git est une recette ou une recommandation expliquant comment utiliser Git pour accomplir une tâche de façon cohérente et productive. Les workflows Git encouragent les développeurs et les équipes DevOps à exploiter Git de façon efficace et cohérente. Git procure une grande flexibilité en matière de gestion des changements. Git étant axé sur la flexibilité, il n'existe aucun processus standardisé pour interagir avec lui. Lorsque vous travaillez en équipe sur un projet géré dans Git, il est important de vous assurer que l'équipe est sur la même longueur d'onde quant à la méthode utilisée pour appliquer les changements. Pour vous assurer que c'est le cas, vous devriez développer ou sélectionner un workflow Git accepté par tous. Plusieurs workflows Git publiés pourraient répondre aux besoins de votre équipe. Ici, nous allons aborder plusieurs de ces options de workflow Git.
Dans la mesure où il peut y avoir différents workflows possibles, il peut s'avérer difficile de savoir quand commencer l'implémentation de Git sur le lieu de travail. Cette page pose les bases en examinant les workflows Git les plus courants pour les équipes de développement.
Lorsque vous la lirez, gardez à l'esprit que ces workflows sont conçus pour servir de références et ne constituent pas des règles concrètes. Nous voulons vous montrer ce qui est possible. Vous pouvez donc combiner différents workflows pour répondre à vos besoins spécifiques.
Qu'est-ce qu'un bon workflow Git ?
Lorsque vous évaluez un workflow pour votre équipe, le plus important est de tenir compte de votre culture. Votre workflow doit améliorer l'efficacité de votre équipe, sans toutefois compromettre la productivité. Voici quelques points à prendre en considération lorsque vous évaluez un workflow Git :
- Ce workflow s'adapte-t-il à la taille des équipes ?
- Est-il facile de corriger les erreurs et les fautes commises dans ce workflow ?
- Ce workflow impose-t-il à l'équipe une nouvelle charge cognitive inutile ?
Workflow centralisé
Le workflow centralisé est idéal pour les équipes qui migrent de SVN vers Git. À l'instar de Subversion, le workflow centralisé utilise un dépôt centralisé qui sert de point d'entrée unique pour tous les changements apportés au projet. Au lieu de trunk
, la branche de développement par défaut se nomme main
, et tous les changements sont commités dans cette branche. Ce workflow ne requiert pas d'autres branches que main
.
Migrer vers un système de contrôle de version distribué peut sembler intimidant, mais vous n'avez pas besoin de changer votre workflow existant pour profiter des avantages de Git. Votre équipe peut développer des projets en travaillant de la même manière qu'avec Subversion.
Cependant, l'utilisation de Git pour renforcer votre workflow de développement présente un certain nombre d'avantages par rapport à SVN. Tout d'abord, il fournit à chaque développeur sa propre copie locale du projet global. Cet environnement isolé permet à chaque développeur de travailler sans tenir compte de tous les autres changements apportés à un projet. Il est possible d'ajouter des commits dans le dépôt local et d'ignorer les développements amont jusqu'à ce qu'ils s'avèrent utiles.
En second lieu, vous avez accès au puissant modèle de création de merges et de branches de Git. Contrairement à SVN, les branches Git sont conçues comme un mécanisme de sécurité pour l'intégration du code et le partage des changements entre les dépôts. Le flux de travail centralisé est similaire aux autres flux de travail, puisqu'il fait appel à un dépôt distant hébergé côté serveur à partir duquel les développeurs font des push et des pull. Comparé aux autres flux de travail, le flux de travail centralisé ne comprend pas de modèle de pull request ou de création de fork défini. Il est généralement plus adapté aux équipes qui migrent de SVN vers Git ainsi qu'aux équipes de petite taille.
Ressource connexe
Commande git log avancée
DÉCOUVRIR LA SOLUTION
Découvrir Git avec Bitbucket Cloud
Fonctionnement
Les développeurs commencent par cloner le dépôt centralisé. Dans leurs propres copies locales du projet, ils modifient les fichiers et commitent des changements comme ils le feraient avec SVN ; néanmoins, ces nouveaux commits sont stockés localement. Ils sont totalement isolés du dépôt centralisé. Les développeurs peuvent ainsi reporter la synchronisation amont jusqu'à ce qu'ils atteignent un point d'arrêt pratique.
Pour publier les changements dans le projet officiel, les développeurs font un « push » de leur branche main
locale vers le dépôt centralisé. Cette opération est similaire à svn commit
, à cela près que tous les commits locaux qui n'ont pas encore été intégrés à la branche main
centrale sont ajoutés.
Initialiser le dépôt centralisé
En premier lieu, un utilisateur doit créer le dépôt centralisé sur un serveur. S'il s'agit d'un nouveau projet, vous pouvez initialiser un dépôt vide. Sinon, vous devez importer un dépôt Git ou SVN existant.
Les dépôts centraux doivent toujours être des dépôts bruts (ils ne doivent pas avoir de répertoire de travail) qui peuvent être créés comme suit :
ssh user@host git init --bare /path/to/repo.git
Assurez-vous d'utiliser un nom d'utilisateur SSH valide pour user
, le domaine ou l'adresse IP de votre serveur pour host
, et l'emplacement dans lequel vous souhaitez stocker votre dépôt pour /path/to/repo.git
. Remarque : l'extension .git
est habituellement utilisée pour indiquer que le dépôt est brut.
Dépôts centralisés hébergés
Les dépôts centralisés sont souvent créés par des services d'hébergement Git tiers, comme Bitbucket Cloud. Le processus d'initialisation d'un dépôt brut abordé ci-dessus est géré pour vous par le service d'hébergement. Celui-ci vous fournit ensuite l'adresse du dépôt centralisé, afin de vous permettre d'y accéder depuis votre dépôt local.
Cloner le dépôt centralisé
Ensuite, chaque développeur crée une copie de tout le projet en local. Cette opération s'effectue via la commande git clone :
git clone ssh://user@host/path/to/repo.git
Lorsque vous clonez un dépôt, Git crée automatiquement un raccourci nommé origin
qui pointe vers le dépôt « parent », au cas où vous souhaiteriez interagir avec lui à une étape ultérieure.
Apporter des changements et commiter
Une fois le dépôt cloné en local, un développeur peut apporter des changements à l'aide du processus de commit Git standard. Si vous n'êtes pas familier de la zone de staging, celle-ci vise à préparer un commit sans avoir à inclure chaque changement dans le répertoire de travail. Ainsi, vous pouvez créer des commits très ciblés, même si vous avez effectué un grand nombre de changements locaux.
git status # View the state of the repo
git add <some-file> # Stage a file
git commit # Commit a file</some-file>
N'oubliez pas que puisque ces commandes créent des commits locaux, Jean peut répéter ce process autant de fois qu'il le souhaite sans avoir à se soucier de ce qu'il se passe dans le dépôt centralisé. Cela peut s'avérer très utile pour les fonctionnalités volumineuses qui nécessitent d'être divisées en blocs plus simples.
Faire un push des nouveaux commits vers le dépôt centralisé
Une fois que le dépôt local comprend de nouveaux changements commités, vous devez en faire un push pour les partager avec les autres développeurs travaillant sur le projet.
git push origin main
Cette commande fait un push des nouveaux changements commités vers le dépôt centralisé. Lorsque vous faites un push de changements vers le dépôt centralisé, il est possible que des mises à jour d'un autre développeur déjà pushées contiennent du code qui entre en conflit avec les vôtres. Git émet alors un message indiquant ce conflit. Dans cette situation, vous devrez d'abord exécuter la commande git pull
. Ce scénario de conflit sera développé dans la section suivante.
Gestion des conflits
Le dépôt centralisé représente le projet officiel. L'historique des commits doit donc être considéré comme sacré et immuable. Si les commits locaux d'un développeur diffèrent du dépôt centralisé, Git refusera de pusher les changements, car cela écraserait les commits officiels.
Dans la mesure où les développeurs peuvent publier leur fonctionnalité, ils doivent fetcher les commits centraux mis à jour et rebaser leurs changements sur ces commits. Cela revient à dire : « Je veux ajouter mes modifications à tout ce qui été fait par les autres ». Résultat : un historique parfaitement linéaire, comme dans les workflows SVN traditionnels.
Si des changements apportés en local entrent en conflit direct avec les commits réalisés en amont, Git interrompt le rebase pour vous permettre de résoudre les conflits manuellement. L'avantage de Git est qu'il utilise les commandes git status
et git add
pour générer des commits et résoudre les conflits de merge. Ainsi, les développeurs débutants peuvent gérer leurs propres merges plus facilement. Avec Git, il est en outre très facile d'abandonner complètement un rebase pour effectuer une nouvelle tentative (ou demander de l'aide) en cas de problème.
Exemple
Examinons étape par étape comment une petite équipe peut collaborer en utilisant ce workflow. Nous verrons comment deux développeurs, Jean et Marie, peuvent travailler sur des fonctionnalités distinctes et partager leurs contributions via un dépôt centralisé.
Jean travaille sur sa fonctionnalité
Dans son dépôt local, Jean peut développer des fonctionnalités en utilisant le processus de commit Git standard : édition, staging et commit.
N'oubliez pas que, puisque ces commandes créent des commits locaux, Jean peut répéter ce processus autant de fois qu'il le souhaite sans avoir à se soucier de ce qui se passe dans le dépôt centralisé.
Marie travaille sur sa fonctionnalité
Dans le même temps, Marie travaille sur sa propre fonctionnalité dans son dépôt local en utilisant le même processus (édition, staging et commit). Tout comme Jean, elle ne se préoccupe pas de ce qu'il se passe dans le dépôt centralisé et elle ne se soucie vraiment pas de ce que Jean fait dans son dépôt local, puisque tous les dépôts locaux sont privés.
Jean publie sa fonctionnalité
Une fois que Jean aura terminé de développer sa fonctionnalité, il devra publier ses commits locaux dans le dépôt centralisé pour que les autres membres de l'équipe puissent y accéder. Pour ce faire, il peut utiliser la commande git push comme suit :
git push origin main
Souvenez-vous qu'origin
constitue la connexion distante avec le dépôt centralisé que Git a créé lorsque Jean l'a cloné. L'argument main
indique à Git de faire de la branche main
d'origin
sa branche main
locale. Comme le dépôt centralisé n'a pas été mis à jour depuis que Jean l'a cloné, l'opération se déroulera sans conflit, et le push fonctionnera comme prévu.
Marie tente de publier sa fonctionnalité
Voyons ce qu'il se passe si Marie tente de pusher sa fonctionnalité après que Jean a publié ses changements dans le dépôt centralisé. Elle peut utiliser la même commande push :
git push origin main
Mais comme son historique local diverge du dépôt centralisé, Git refusera la requête et renverra un message d'erreur détaillé :
error: failed to push some refs to '/path/to/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Cela empêche Marie d'écraser les commits officiels. Elle doit faire un pull des mises à jour de Jean dans son dépôt, les intégrer avec ses changements locaux, puis réessayer.
Marie fait un rebase par-dessus le ou les commits de Jean
Marie peut lancer git pull pour intégrer à son dépôt les changements effectués en amont. Cette commande est très similaire à svn update
: elle fait un pull de tout l'historique du commit en amont dans le dépôt local de Marie et tente de l'intégrer à ses commits locaux :
git pull --rebase origin main
L'option --rebase
indique à Git de déplacer tous les commits de Marie vers la pointe de la branche principale
après l'avoir synchronisée avec les changements issus du dépôt centralisé, comme l'illustre le schéma suivant :
Le pull fonctionnera toujours si vous oubliez cette option, mais vous vous retrouverez avec un commit de merge superflu à chaque fois qu'un utilisateur devra synchroniser son dépôt avec le dépôt centralisé. Pour ce workflow, il est toujours préférable de procéder à un rebase plutôt que de générer un commit de merge.
Marie résout un conflit de merge
Lors du rebase des projets, chaque commit local est individuellement transféré vers la branche main
mise à jour. Cela signifie que vous traitez les conflits de merge commit par commit, plutôt que de les résoudre tous dans un seul grand commit de merge. Vos commits seront aussi orientés que possible, et l'historique de votre projet restera propre. Ainsi, il vous sera nettement plus facile de détecter l'origine de bugs et, si nécessaire, d'annuler les changements tout en limitant l'impact de ces opérations sur l'ensemble du projet.
Si Marie et Jean travaillent sur des fonctionnalités non liées, il est peu probable que le process de rebase génère des conflits. Si c'est le cas, Git interrompt le rebase au commit actuel et affiche le message suivant avec des instructions pertinentes associées :
CONFLICT (content): Merge conflict in <some-file>
Le grand avantage de Git est que chaque développeur peut résoudre ses propres conflits de merge. Dans notre exemple, Marie doit simplement exécuter la commande git status pour identifier l'origine du problème. Les fichiers en conflit apparaîtront dans la section Chemins non mergés :
# Unmerged paths:
# (use "git reset HEAD <some-file>..." to unstage)
# (use "git add/rm <some-file>..." as appropriate to mark resolution)
#
# both modified: <some-file>
Ensuite, elle modifiera le ou les fichiers à sa convenance. Une fois qu'elle sera satisfaite du résultat, elle pourra stager le ou les fichiers de la manière habituelle, puis laisser la commande git rebase faire le reste :
git add <some-file>
git rebase --continue
Le tour est joué. Git passe au commit suivant et répète le process pour tous les commits qui génèrent des conflits.
Si vous n'avez pas la moindre idée de ce qu'il se passe à ce stade, pas de panique ! Il vous suffit d'exécuter la commande suivante pour revenir au point de départ :
git rebase --abort
Marie publie avec succès sa fonctionnalité
Après avoir synchronisé le dépôt centralisé, Marie pourra publier ses changements avec succès :
git push origin main
Marche à suivre
Comme vous pouvez le voir, il est possible de répliquer un environnement de développement Subversion classique avec seulement quelques commandes Git. C'est intéressant pour la migration d'équipes hors du dépôt SVN, mais cela n'exploite pas la nature distribuée de Git.
Le workflow centralisé est idéal pour les petites équipes. Le processus de résolution de conflits détaillé ci-dessus peut constituer un goulot d'étranglement à mesure que votre équipe s'agrandit. Si votre équipe est à l'aise avec le workflow centralisé, mais souhaite simplifier ses efforts de collaboration, il est sans doute intéressant d'étudier les avantages du workflow de branche de fonctionnalité. En dédiant une branche isolée à chaque fonctionnalité, il est possible d'entamer des discussions approfondies sur les nouveaux ajouts avant de les intégrer au projet officiel.
Autres workflows courants
En bref, le workflow centralisé est un élément de base d'autres workflows Git. Les workflows Git les plus populaires impliquent une forme quelconque de dépôt centralisé à partir duquel les développeurs font des push et des pull. Dans la section suivante, nous allons brièvement évoquer certains autres workflows Git populaires. Ces workflows étendus offrent davantage de modèles spécialisés en ce qui concerne la gestion des branches pour le développement de fonctionnalités et de correctifs et, enfin, la livraison.
Création de branches de fonctionnalités
La création de branches de fonctionnalité est une extension logique du workflow centralisé. Le principe de base du workflow de branche de fonctionnalité est que chaque fonctionnalité est développée dans une branche dédiée plutôt que dans la branche main
. Grâce à cette encapsulation, plusieurs développeurs peuvent travailler aisément sur une même fonctionnalité sans modifier la base de code principale. Cela signifie également que la branche main
ne contiendra jamais de code bugué : un avantage non négligeable pour les environnements d'intégration continue.
Workflow Gitflow
Le workflow Gitflow a tout d'abord été publié dans un billet de blog très médiatisé de 2010, par Vincent Driessen de chez nvie. Le workflow Gitflow définit un modèle de branches strict conçu autour de la version du projet. Il n'ajoute aucun nouveau concept ni aucune nouvelle commande en dehors de ce qui est exigé pour le workflow de branche de fonctionnalité. Il assigne plutôt des rôles très spécifiques aux différentes branches et définit comment et quand elles doivent interagir.
Workflow de duplication (fork)
Le workflow de duplication (fork) est fondamentalement différent des autres workflows abordés dans ce tutoriel. Au lieu d'utiliser un dépôt unique côté serveur qui fera office de base de code « centralisée », ce workflow fournit un dépôt côté serveur à chaque développeur. Par conséquent, chaque contributeur dispose non pas d'un, mais de deux dépôts Git : un local privé et un côté serveur public.
Recommandations
Il n'existe pas de modèle unique de workflow Git adapté à toutes les circonstances. Comme nous l'avons déjà dit, il est important de développer un workflow Git qui améliore la productivité de votre équipe. Outre la culture d'équipe, un workflow doit compléter la culture d'entreprise. Les fonctionnalités Git comme les branches et les tags devraient compléter le planning de livraison de votre entreprise. Si votre équipe utilise un logiciel de gestion de projet et de suivi des tâches, vous souhaiterez peut-être utiliser des branches qui correspondent aux tâches en cours. En outre, voici quelques recommandations à prendre en compte lorsque vous déterminez le workflow à utiliser :
Branches éphémères
Plus une branche est séparée de la branche de production, plus le risque de conflits de merge et de difficultés de déploiement est élevé. Les branches éphémères favorisent des merges et des déploiements plus propres.
Minimiser et simplifier les reverts
Il est important d'avoir un workflow qui contribue à prévenir, de façon proactive, les merges qui devront être restaurés. Un workflow qui teste une branche avant de permettre qu'elle ne soit mergée dans la branche main
, par exemple. Cependant, vous n'êtes pas à l'abri des accidents. Cela dit, il est utile de mettre en place un workflow qui permet des reverts faciles, sans interrompre le travail des autres membres de l'équipe.
Faire coïncider le workflow avec le planning de livraison
Un workflow doit compléter votre cycle de développement et de livraison. Si vous prévoyez de livrer plusieurs fois par jour, il vous faut conserver une branche principale
stable. Si votre planning de livraison est moins fréquent, vous souhaiterez peut-être utiliser des tags Git pour taguer une branche à une version.
Résumé
Dans ce document, nous avons abordé les workflows Git. Nous avons étudié en détail un workflow centralisé avec des exemples pratiques. Pour aller plus loin, nous avons vu des workflows spécialisés supplémentaires. Voici les enseignements clés de ce module :
- Il n'existe pas de modèle de workflow Git universel
- Un workflow doit être simple et améliorer la productivité de votre équipe
- Vos exigences métier devraient vous aider à façonner votre workflow Git
Pour découvrir le prochain workflow Git, consultez notre décomposition détaillée du workflow de branche de fonctionnalité.
Partager cet article
Thème suivant
Lectures recommandées
Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.