Workflow Git : vers le Full Merge-Request
Il y a un peu plus d’an que nous sommes passés en workflow git full merge-request. Voici les étapes que nous avons suivies et notre ressenti sur cette nouvelle façon de collaborer autour du code.
Apprendre Git
Avant de pouvoir passer en workflow git full merge-request, nous avons commencé par apprendre Git. Pas un outil qui pré-mâche les commandes Git, pas un outil graphique, pas un outil intégré à notre IDE, mais les commandes Git de base. Un dépôt (repository dans le jargon Git), une console et quelques heures plus tard, nous pouvions utiliser Git comme nous utilisions Svn. En effet, une fois qu’on a compris que le dépôt local est différent du dépôt distant, et qu’il nous faut synchroniser les deux de temps en temps, tout devient plus clair.
Voici les commandes que nous suivions :
git add [-A] . //ajoute les modifications du code courant dans notre dépôt local git commit -m "explications" //valide l'ajout du code précédent git pull --rebase //récupère les modifications de code des autres développeurs git push //envoie nos modifications sur le dépôt distant
Voici le petit mémo que j’ai imprimé et collé dans tous les bureaux : Commandes Git (pdf)
Très rapidement, nous sommes rentrés dans le vif du sujet en créant des branches.
Git : les branches
Git est un gestionnaire de version basé sur les différences de code. Entre 2 commits, Git garde uniquement les différences. Une branche est le fait de mettre de côté un certain nombre de changements. Elle permet également d’être nommée ce qui permet de revenir à un état du code facilement. Dans Git tout est branche. Au départ, votre dépôt est composé d’une unique branche : « master ».
Pour continuer à apprendre Git en douceur, nous avons fait le choix de créer une branche par feature. Dès lors que la feature est finie nous la mergions dans master et la supprimions.
Ce petit workflow git nous a permis de nous casser les dents sur les merges. En effet, garder un arbre de commits propre est chose difficile. Pour ce faire, nous utilisions les commandes suivantes :
# récupération du code partagé et création d'une branche pour la nouvelle feature git pull --rebase origin master //le rebase permet de placer notre code local par dessus le code distant git checkout -b num-branchName # dev git add [-A] . git commit -m "[num] explication" # à la fin git checkout master git pull --rebase origin master git checkout num-branchName git rebase master git checkout master git merge --no-ff num-branchName git push origin master git branch -d num-branchName
Si vous vous demandez pourquoi nous ajoutions le « [num] » de la feature dans le commit en plus du nom de la branche, c’est tout simplement pour garder une trace. En effet, une fois la branche supprimée, nous nous retrouvions avec des commits du style « Changement de la couleur » : pour savoir à quelle page ça se réfère nous devions aller voir dans le code… Pas top !
En cadeau voici la feuille d’aide que j’ai distribué à tous les développeurs : workflow git (pdf). Je ne leur ai pas donné sous forme pdf afin qu’ils ne fassent pas de copier/coller. J’ai préféré leur imprimer pour qu’ils soient conscients des lignes qu’ils tapent !
Bien sûr il existe pléthores de raccourcis pour exécuter ces actions. Mais n’oubliez pas que notre but était de comprendre et d’apprendre Git.
Git : les dépôts
Une merge-request est une proposition de modification de code. Un ou plusieurs développeurs peuvent alors décider d’accepter ou de refuser cette modification. On peut réaliser une merge-request intra-dépôt mais nous souhaitions conserver un dépôt commun propre. Nous nous sommes donc tournés vers une architecture décentralisée.
Pour cela, nous avons utilisé le fait qu’un même code source peut avoir plusieurs dépôts. Ainsi nous pouvons proposer une modification de code de notre dépôt personnel vers celui du projet (que toute l’équipe partage).
C’est exactement comme ça que fonctionne Github et tout l’éco-système open-source. Pour proposer un patch à un projet open-source, vous commencez par forker le projet, et donc vous créez un dépôt personnel. Vous travaillez sur votre dépôt et lorsque vous êtes satisfait de votre travail vous le proposez sous forme de pull-request.
Dans cet article je parle de merge-request et non de pull-request car nous utilisons en interne Gitlab au lieu de Github. Les termes sont un peu différents mais le concept est exactement le même.
Workflow git : full merge-request
Voici résumé en un schéma notre architecture décentralisée des dépôts Git :
Ainsi chaque développeur a un dépôt que nous appelons par convention « origin » et chaque projet à un dépôt que nous appelons (toujours par convention) « upstream ». Cette fois-ci la liste des commandes est un peu plus longue puisque nous devons synchroniser notre origin avec upstream :
# les 3 commandes suivantes seront raccourcies en $synchro par la suite git checkout master git pull –rebase upstream master git push origin master #je commence une feature git checkout -b num-branchName # dev git add [-A] . git commit -m "[num] explication" git push origin num-branchName $synchro git checkout num-branchName git rebase master git push origin num-branchName # aller sur votre GitLab # aller dans le projet « racine » # onglet « Merge Requests » # bouton « New Merge Request » # dans « Source branch » sélectionner votrelogin/nomprojet puis la num-branchName # dans « Target branch » sélectionner nomprojet/nomprojet puis la branch master # review du code et corrections demandées $synchro git checkout num-branchName git push origin num-branchName # review du code et acceptation, donc merge de num-branchName dans upstream/master $synchro git branch -d num-branchName git push origin :num-branchName
Comme vous pouvez le voir une grande partie du travail s’effectue directement dans Gitlab (ou dans Github).
Ce système décentralisé à bien des avantages. Si un de nos collègues tombe malade, il nous suffit de rajouter son origin à nos dépôts et nous pouvons continuer sa feature. De plus, nous devons valider tout ce qui passe d’un origin vers un upstream. Ça permet de partager la connaissance du code. De faire appliquer les « bonnes pratiques de code » ou encore de repérer des bugs potentiels avant même qu’ils ne soient récupérés par d’autres développeurs.
De plus, nous avons intégré notre intégration continue à ce moment là. Donc toute merge-request créée entraîne l’exécution de tous nos tests unitaires, d’intégrations, de performances et de qualité. Ça fera sûrement l’occasion d’un article plus tard.
En bonus final, voici la feuille d’aide que j’ai également imprimé pour chaque développeur : Workflow git V2.
Git : bonus
Lorsque nous avons été suffisamment à l’aise avec Git et ce workflow nous avons commencé à nous amuser avec des commandes plus pointues. En voici quelques unes :
git rebase -i master
Permet de rebaser en mode interactif et ainsi pouvoir supprimer/renommer/fusionner certains commits intermédiaires. Particulièrement utile si vous devez synchroniser sans avoir fini votre travail ou si, comme moi, vous oubliez systématiquement le numéro de ticket de la feature.
git synchro
Ne la cherchez pas dans la documentation de git, cette commande n’existe pas. Mais avec git il est très facile d’ajouter des commandes. Suivez la doc pour en savoir plus !
Git : multiples dépôts & multiples branches
Maintenant que nous maîtrisons les branches et les dépôts, nous commençons doucement à gérer des cas plus complexes sur upstream.
Par exemple, lorsque nous avons un gros rework à faire. Ce rework durera certainement plusieurs sprints et nous ne voulons pas bloquer d’autres features en parallèle. Nous pouvons créer une branche « feature » sur upstream et faire nos merge-requests, non plus sur upstream/master mais sur upstream/feature. Le moment venu nous pourrons faire une merge-request de upstream/feature vers upstream/master pour intégrer notre gros rework.
De même, nous pouvons maintenir une branche « production » et y appliquer des hot-fix si nécessaire.
Mon article, mon avis
Si vous n’avez jamais essayé un workflow git de ce type, je vous recommande fortement de contribuer à un projet open-source sur Github. Vous serez très rapidement convaincus. Nous avons d’ailleurs commencé Git avec nos H-Day sur Github.
Ici en interne ça a radicalement changé notre façon de travailler. Nous avons beaucoup moins de régression, la qualité de notre code est bien meilleure. Enfin la fameuse phrase « c’est pas moi qui ai fait cette partie, je peux pas continuer la feature. » est complètement absente de notre vocabulaire (remplacée par : « Ho t’abuses de me refuser cette merge-request pour un espace manquant » :D).
Pour plus de fun, n’oubliez pas le petit gif animé sur la merge-request, ici en interne, nous en avons de vrais spécialistes !
On pourrait même ajouter que Jenkins et Sonar peuvent participer aux discussions des merge request en y ajoutant respectivement les résultats du build et les alertes de qualité de code !
Bonjour,
pourquoi re checkout sur master et pas simplement
git pull –rebase origin master sur la branche actuelle ?