Déjà, je vous promets que la photo de couverture a un vrai rapport avec les commits ! 🙏 Trust me.

Dans toutes les équipes que j’ai rencontrées, la même question se pose par rapport à Git.

« Quels messages utiliser pour nos commits ? »

Cette question, elle peut paraître annondine. Mais en fait pas du tout.
De la même façon qu’on doit tout faire pour éviter les plans de métro, il faut faire en sorte que les stations commits de notre graph soient lisibles.

Pour autant, tous les commits ne se valent pas.

Alors comment faire ?

En vrai, je n’ai pas de façon qui fonctionne à 100%.
Je vais vous présenter 3 possibilités.

Je vous le dis direct: j’en préfère une aux deux autres… mais toutes fonctionnent.


🎾 Les différents commits

La première chose à savoir, c’est que je considère qu’il y a « 2 types » de commits sur git.

  • Les commits de « branche« 
  • Les commits de « merge« 

Les commits de branche

Les commits de branche sont ceux que vous faites tous les jours, à chaque modification de votre code.

Finalement, dès que vous faites un git commit, je considère que c’est un commit de branche.

⤵️ Les commits de merge

Les commits de « merge » sont ceux qui se passent lorsque vous rapatriez votre branche dans la branche partagée par tous. develop en général.

Si vous passez par les outils automatiques sans rien toucher, ils se matérialisent souvent par un message classique du type

Merge the_branch_to_merge into the_target_branch

Par exemple : Merge feat/tartampion into develop


🏷 Les stratégies de nommage

🔎 Zoom sur la « Angular Convention »

La « angular convention » c’est une façon de nommer ses commits.
Elle est de plus en plus répandue dans le milieu de l’IT et de nombreuses équipes l’utilisent (en se l’appropriant un peu).

Le principe est le suivant, les commits doivent tous avoir la même nomenclature, à savoir:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

Ou, de manière plus sumple what( where ): why

Le what, c’est le type de travail qu’on vient de réaliser

  • feat (pour une nouvelle feature/fonctionalité)
  • fix (pour un bug fix)
  • docs (ajout de documentation)
  • style (reformat de fichier, indentation, …)
  • refactor (… voilà)
  • test (ajout de tests)
  • chore (les choses autour du projet qui n’apportent pas forcément de valeur client, par exemple la ci/cd ou autres)

Le where, ça correspond au scope sur lequel vous avez travaillé, c’est très lié à la découpe que vous voulez faire sur votre projet et c’est plus une convention d’équipe que quelque chose de figé

  • Découpage applicatif ? (home screen, profile, connection, etc)
  • En utilisant les Epics agiles de votre projet ?

Et enfin le why, pourquoi ce commit, qu’est-ce qu’il ajoute.
Ici aussi, c’est votre équipe qui décide, maintenant j’ai quelques conseils pour vous

  • La user story pure et dure (ou la remontée de bug si besoin)
  • Un résumé du travail effectué

Dans le why, si vous utilisez un outil de ticketting, vous pouvez le lier, mais histoire de rester agnostique, je vous invite à ajouter le #ticket_number.

Par exemple:

  • feat(connection): #123 As a user, I want to sign in with my google account
  • fix(profile): #345 The profile picture does not work when coming from gravatar
  • docs(homepage): Add doc on the items classification algorithm.
  • Etc etc…

Encore une fois, beaucoup de choses dépendent de de vos choix d’équipe !

  • français ou anglais ?
  • #ticket ou pas ?
  • etc…

Une fois ça mis sur la table, on va se dire 2 choses

  • C’est lisible et ça amène plein de bonnes choses
    (autogénération de readme / changelog, valeure vite perçue, suivi des tickets, MEP très simples entre 2 versions, etc)
  • C’est fastidieux (souvent une US a besoin de plusieurs commits pour être réalisée, sur une branche il y a plusieurs commits), etc…

🤪 Quand utiliser quoi ?

Alerte, opinion incoming.

C’est mon avis ici… Parce que je le vois dans les équipes, quand on commence à dire « on utilise l’angular convention » les devs l’utilisent PARTOUT.

Genre PARTOUT, à chaque commit. Ce qui pose plusieurs problèmes:

  • Des branches qui sont réduites à 1 commit, et v’la le bordel si on perd le boulot (parce qu’on perd tout l’intérêt de git)
  • Ou alors des branches complétement illisibles (avec du feat/fix/doc partout dans la branche)
  • Mais surtout les branches n’ont plus de sens (3 feats dans une branche ? ce n’est pas une branche c’est une release)

Donc mon conseil:

  • Dans vos branches, vous faites CE QUE VOUS VOULEZ !
    Si vous avez envie de commit à base de toto/tata/tutu/test/blabla/fix/wip/audauigdxi faites le !
  • Dans les commits de merge, suivez RIGOUREUSEMENT la convention.

Maintenant, on va voir que selon les « stratégies » de merge, cela peut un peu être adapté et évoluer.

NB: Quand je dis faites ce que vous voulez, c’est quand même mieux que le message soit un minimum représentatif du taf que contient le commit. Maintenant le fix; fix fix; fuck; it should work now de 3h du mat on l’a tous fait on n’va pas s’mentir. 😏


🔂 Les stratégies de merge

Lorsque notre travail sur notre branche est fini, on ouvre généralement une pull request (ou vous mergez sur develop).

Dans les 2 cas, vous avez plusieurs choix sur la « façon » de merger votre branche dans develop.

Dans tous les cas, je vous invite à éviter les plans de métro et à rebaser vos branches avant d’ouvrir des PR.

Partons d’un cas classique, une branche pour une US de feature

As a user, I want to sign in with my Google Account

Le developpement s’est fait en 3 commits.
Un qui ajoute la stack google et le métier. Un pour fixer le google id qui était mauvais et un dernier pour ajouter le sign in btn sur la login page.

On a donc un graph qui ressemble à celui-ci:

Etape 1, sur notre branche, on ajoute la fonctinonalité, on appelle les commits comme on veut, on rebase, et vient le moment d’ouvrir la PR

Allons-y, on ouvre la PR !

👊 Le squash

Le squash est une méthode assez simple: il va prendre tous vos commits et les regrouper en 1 seul.

Vous nommez ce commit, et il l’ajoute en « fast-forwars » à la branche de destination.

Dans une situation où votre stratégie est le squash, seul le nom de ce « commit » de merge importe.
Les autres commits sont de toute façon supprimés à la fin.

1/ Les commits sont « squashés » en 1 seul commit unique.
2/ Ce même commit est ajouté au tree de develop
en « fast-forward » avec un nom correct

Avantages:

  • On peut appeler nos commits de branche n’importe comment (ça ne veut pas dire qu’il faut), de toute façon, à la fin, ils sont « supprimés ».
  • Le graph du dépôt est très lisible, on a l’impression que chaque feature a été faite à la suite de l’autre en 1 seule fois.

Inconvénients:

  • On va perdre d’une certaine façon l’historique de comment une feature a été faite, moins pratique pour le débug.
Vous en train de chercher la cause d’un bug après un squash

🤘 Le fast-forward

Le pire.

Je ne rigole pas, le fast-forward c’est le pire truc.

En gros, si votre branche part directement de son ascendant et n’a pas de conflit (ce qui est TOUJOURS le cas après un rebase), git va vous proposer de faire un merge en fast forward.

C’est un truc qu’on veut éviter à tout prix (d’où le fait de passer –no-ff en lignes de commandes au git merge).

Pourquoi on veut éviter ça ? Le fast-forward, en gros c’est réintégrer la branche source telle quelle dans la branche de destination.

Donc si on ne fait pas attention, voilà ce qui se passe:

1/ Les commits sont intégrés directement à la branche de destination

Avantages:

  • Aucun, vraiment

Inconvénients:

  • L’obligation de nommer correctement TOUS ses commits
  • On ne sait pas où les features commencent et où elles s’arrêtent
  • Si on n’utilise pas l’angular convention sur le dernier commit c’est le bordel
  • Si on l’utilise sur le dernier commit, elle n’a pas de sens.
  • Fast-forward quoi. C’est le pire truc. 🤮
Votre repo git après quelques merges en fast-forward

👌 Le merge

Le best, le caviar, la crème.

Oui j’ai une légère préférence.

En gros, le merge, ça va prendre le meilleur des 2, ça va créer un commit sur develop, en gardant l’historique de la branche.

Même si un fast-forward est possible, je vous invite grandement à garder un commit de merge, et c’est ce même commit qui aura la angular convention.

In fine, ça donne ça:

Un commit de merge est créé et l’historique est gardé

Avantages

  • L’historique de la branche est conservé
    (facilite la compréhension et le débug)
  • On peut appeler ses commits de branche comme on veut
    (même si encore une fois, ce n’est pas forcément ce qu’il y a de plus judicieux)
  • Un beau commit de merge ! Et si on ne veut voir que ceux là c’est possible
    (git log –merges)
  • Possible de générer son changelog automatiquement
  • Rebase IZI de vos branches

Inconvénients

  • Je n’en vois pas vraiment.
    À la limite, si on veut pinailler, on peut dire qu’on garde un paquet de commits « inutiles » par rapport au squash. Mais pour moi ça facilite le debug donc.
penderie bien rangée
Un repo git bien propre et bien rangé 💚

🧠 Conclusion

Bien nommer ses commits c’est vraiment quelque chose d’important.

C’est surement tout aussi important que de ne pas faire de plan de métro dans son graph.

L’angular convention quant à elle, c’est un choix d’équipe, c’est ce que je vous propose ici car ça va vous permettre de facilement générer des changelog entre 2 versions.

Avec des méthodes comme celles-ci, en un coup d’oeil, on voit où en est dans l’avancée des features / fix / docs / etc. Et pour le suivi d’un projet aussi bien technique que fonctionnel.

Ici, on parle aussi beaucoup de pull requests (PR) et à mon avis c’est un passage obligatoire.

Dire « qu’on n’a pas le temps de faire des PR » ou que « ça sert à rien » dans un projet c’est avouer que c’est déjà un échec.

Une bonne utilisation de git peut vraiment vous faciliter la vie, tout comme une mauvaise utilisation vous la rendre désastreuse.

Faites votre choix, moi j’pense la question elle est vite répondue.


Liens des photos

Dernière modification: 10 juillet 2020