Logo SmartBooster Playbook

Merge request

Préparer sa merge request pour la revue de code, puis traiter les retours et nettoyer ses branches.

La merge request est le moment où du code poussé sur le dépôt peut être relu, puis fusionné avec la branche cible. Cette branche cible est la branche de base d’où la branche courante a été tirée, sauf changement de priorité décidé en cours de route.

Bien préparer cette étape n’est pas une politesse envers le reviewer : une merge request mal préparée fait porter la revue sur sa mise en forme au lieu du code, et c’est autant de temps qui n’est pas passé à chercher ce qui compte.

Nettoyer son historique avant de soumettre

Avant même de créer la merge request, l’historique des commits de la branche doit être propre :

  • chaque message porte l’identifiant du ticket en préfixe et décrit l’étape réalisée
  • le message est explicite : il donne un aperçu des modifications sans avoir à ouvrir le diff
  • les commits successifs sur un même sujet avec peu de contenu sont regroupés pour réduire le nombre de commits

Lorsque vous rédigez un message de commit, vous devez penser à la personne qui s’en servira : à la relecture de la merge request pour comprendre les étapes du travail, à la recherche d’un bug dans l’historique d’un fichier, et en amont d’une livraison pour savoir ce qui part en production.

Le nettoyage se fait au rebase interactif :

git rebase -i <hash_du_commit_ou_demarre_le_rebase>

Deux options couvrent la quasi-totalité des cas dans le prompt affiché :

  • r, reword pour reprendre le message d’un commit
  • s, squash pour combiner le contenu d’un commit avec celui du précédent

Si la branche était déjà poussée, le rebase réécrit son historique : elle doit être repoussée avec l’option force.

# Seul intervenant sur la branche
git push -f origin <nom_branche_courante>

# Travail collaboratif sur la branche
git push --force-with-lease origin <nom_branche_courante>

-f écrase la branche distante sans poser de question. C’est acceptable tant que vous êtes seul à travailler sur la branche. Dès que quelqu’un d’autre y contribue ou a tiré sa propre branche depuis la vôtre, utilisez --force-with-lease : la commande compare d’abord la branche distante à ce que vous en connaissez, et refuse le push si quelqu’un a poussé entre-temps au lieu d’effacer son travail sans le signaler.

Créer la merge request

Nom : le même format que la branche, soit l’identifiant du ticket en préfixe suivi du contenu.

Description : tout ce qui sort du cadre de développement classique, pour que le reviewer ne le découvre pas dans le diff. Par exemple :

  • un changement important par rapport à la mise en place évoquée à la présentation du ticket
  • l’explication du choix d’une nouvelle librairie
  • une précision sur un TODO laissé dans les commits
  • un lien vers une donnée de test en intégration pour illustrer un cas précis

Assigné : la personne en charge du code, celle qui traitera les demandes de modification. Reviewer : la personne responsable de la revue. Elle ne se choisit pas au moment de créer la merge request, elle est désignée dans les étapes de validation du ticket, écrites à la conception. Branche cible : si la branche n’est pas basée sur main, changer la cible pour la branche de base réelle.

Deux options complètent la création. L’option de suppression de la branche source une fois la merge request acceptée reste activée, pour ne pas laisser s’accumuler des branches mortes sur le dépôt. Et si le code est soumis uniquement pour un premier avis, sans intention de le livrer, la merge request est marquée comme brouillon (Mark as draft).

Une merge request en brouillon ne peut pas être fusionnée. C’est aussi ce qui permet de temporiser l’ordre d’intégration de plusieurs merge requests, le temps de finaliser des retours ou de réassigner le sujet à quelqu’un d’autre.

Le reviewer n’est positionné et notifié qu’une fois le job de tests de l’intégration continue au vert. Solliciter une relecture sur une branche dont les tests échouent fait simplement perdre du temps au reviewer et au projet.

Une fois le reviewer notifié, la revue se fait dès que possible. Son moment exact s’organise en fonction de la priorité du ticket, de la difficulté de la tâche et du planning de chacun. C’est la communication et la justesse des estimations qui rendent l’enchaînement fluide, bien plus qu’un délai imposé : une revue attendue et estimée se cale sans effort, une revue qui tombe sans prévenir désorganise le travail de quelqu’un.

Résoudre les conflits

Si la merge request est signalée en conflit, la correction est à la charge de l’auteur, pas du reviewer ni de la personne qui livre. Il récupère la branche cible et rebase sa branche courante par-dessus, puis repousse une version sans conflit.

# Ici, la branche cible est main
git pull --rebase origin main

https://git-scm.com/book/fr/v2/Les-branches-avec-Git-Rebaser-Rebasing

Traiter les retours de revue

Le traitement dépend de l’ampleur des retours, et il vise toujours à garder la relecture des corrections facile :

  • des retours minimes qui concernent le commit précédent sont ajoutés à ce commit, ce qui nécessite un push force
git commit --amend
# --force-with-lease si vous n'êtes pas seul sur la branche
git push -f origin <nom_branche>
  • des retours répartis sur plusieurs commits font l’objet d’un nouveau commit distinct
  • des retours conséquents sont découpés en plusieurs commits de retour

Comme à l’étape de validation du ticket, c’est à l’auteur de relancer le reviewer si son code reste trop longtemps en merge request ouverte ou en brouillon. Une branche qui dort bloque souvent une livraison ou le travail de quelqu’un d’autre sans que personne ne s’en rende compte.

Nettoyer ses branches locales

Une fois la branche intégrée, l’historique local se nettoie. Ce n’est pas du rangement pour le plaisir : c’est ce qui permet de retrouver ses branches et de choisir ses bases sans hésiter les jours suivants.

# Lister toutes les branches
git branch -a

# Supprimer une branche locale (refusé si elle n'est pas intégrée)
git branch -d <nom_branche>

# Forcer la suppression d'une branche non intégrée
# (utile pour les branches mortes, qu'on ne rebasera ni n'intégrera)
git branch -D <nom_branche>

# La suppression locale n'entraîne pas celle de la branche distante
git push origin --delete <nom_branche>

# Mettre à jour ses références en retirant les branches distantes supprimées
git fetch -p

Une fois la revue passée et le code intégré, le ticket peut passer À valider : la suite est décrite dans valider un ticket.