Contenu : Introduction | Les sept règles | Conseils
- Introduction : Pourquoi de bons messages commit sont importants
- Les sept règles d’un grand message de commit Git
- Séparer le sujet du corps avec une ligne blanche
- Limiter la ligne d’objet à 50 caractères
- Capitalisez la ligne d’objet
- Ne terminez pas la ligne d’objet par un point
- Utiliser l’humeur impérative dans l’objet
- Enveloppez le corps à 72 caractères
- Utiliser le corps pour expliquer quoi et pourquoi vs. comment
- Tips
- Apprenez à aimer la ligne de commande. Laissez l’IDE derrière.
- Lisez Pro Git
Introduction : Pourquoi de bons messages commit sont importants
Si vous parcourez le journal de n’importe quel dépôt Git aléatoire, vous trouverez probablement que ses messages commit sont plus ou moins un désordre. Par exemple, jetez un coup d’œil à ces joyaux de mes premiers jours de commit sur Spring:
$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)147709f Tweaks to package-info.java files22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils7f96f57 polishing
Yikes. Comparez cela avec ces commits plus récents du même dépôt :
$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"5ba3db6 Fix failing CompositePropertySourceTests84564a0 Rework @PropertySource early parsing logice142fd1 Add tests for ImportSelector meta-data887815f Update docbook dependency and generate epubac8326d Polish mockito usage
Quel est celui que vous préférez lire ?
Le premier varie en longueur et en forme ; le second est concis et cohérent.
Le premier est ce qui se passe par défaut ; le second n’arrive jamais par accident.
Bien que les journaux de nombreux dépôts ressemblent au premier, il y a des exceptions. Le noyau Linux et Git lui-même sont de grands exemples. Regardez Spring Boot, ou n’importe quel dépôt géré par Tim Pope.
Les contributeurs de ces dépôts savent qu’un message de commit Git bien rédigé est le meilleur moyen de communiquer le contexte d’un changement aux collègues développeurs (et même à leur futur moi). Un diff vous dira ce qui a changé, mais seul le message commit peut vous dire correctement pourquoi. Peter Hutterer exprime bien ce point :
Rétablir le contexte d’un morceau de code est un gaspillage. Nous ne pouvons pas l’éviter complètement, donc nos efforts devraient aller à le réduire autant que possible. Les messages de commit peuvent faire exactement cela et, par conséquent, un message de commit montre si un développeur est un bon collaborateur.
Si vous n’avez pas beaucoup réfléchi à ce qui fait un excellent message de commit Git, il se peut que vous n’ayez pas passé beaucoup de temps à utiliser git log
et les outils connexes. Il y a là un cercle vicieux : parce que l’historique de commit est non structuré et incohérent, on ne passe pas beaucoup de temps à l’utiliser ou à en prendre soin. Et parce qu’on ne l’utilise pas ou qu’on n’en prend pas soin, il reste non structuré et incohérent.
Mais un journal bien soigné est une chose belle et utile. git blame
, revert
, rebase
, log
, shortlog
et autres sous-commandes prennent vie. Réviser les commits et les pull requests des autres devient quelque chose qui vaut la peine d’être fait, et qui peut soudainement être fait indépendamment. Comprendre pourquoi quelque chose est arrivé il y a des mois ou des années devient non seulement possible mais efficace.
Le succès à long terme d’un projet repose (entre autres) sur sa maintenabilité, et un mainteneur a peu d’outils plus puissants que le journal de son projet. Cela vaut la peine de prendre le temps d’apprendre à en prendre soin correctement. Ce qui peut être un tracas au début devient rapidement une habitude, et finalement une source de fierté et de productivité pour toutes les personnes impliquées.
Dans ce post, j’aborde juste l’élément le plus basique pour garder un historique de commit sain : comment écrire un message de commit individuel. Il y a d’autres pratiques importantes comme le commit squashing que je n’aborde pas ici. Peut-être que je le ferai dans un post ultérieur.
La plupart des langages de programmation ont des conventions bien établies sur ce qui constitue un style idiomatique, c’est-à-dire le nommage, le formatage et ainsi de suite. Il existe des variations sur ces conventions, bien sûr, mais la plupart des développeurs s’accordent à dire que choisir une convention et s’y tenir est bien mieux que le chaos qui s’ensuit lorsque chacun fait sa propre chose.
L’approche d’une équipe à l’égard de son journal de commit ne devrait pas être différente. Afin de créer un historique de révision utile, les équipes devraient d’abord se mettre d’accord sur une convention de message de commit qui définit au moins les trois choses suivantes :
Style. Syntaxe de balisage, marges d’enveloppement, grammaire, capitalisation, ponctuation. Expliquez ces choses, supprimez les conjectures et rendez tout cela aussi simple que possible. Le résultat final sera un journal remarquablement cohérent qui n’est pas seulement un plaisir à lire mais qui est réellement lu sur une base régulière.
Contenu. Quel type d’information le corps du message de commit (s’il y en a un) doit-il contenir ? Que ne doit-il pas contenir ?
Métadonnées. Comment les ID de suivi des problèmes, les numéros de demande de pull, etc. doivent-ils être référencés ?
Heureusement, il existe des conventions bien établies sur ce qui constitue un message de commit idiomatique de Git. En effet, beaucoup d’entre elles sont supposées dans la façon dont certaines commandes Git fonctionnent. Il n’y a rien à réinventer. Il suffit de suivre les sept règles ci-dessous et vous êtes sur la voie de commiter comme un pro.
Les sept règles d’un grand message de commit Git
N’oubliez pas : Tout cela a déjà été dit.
- Séparer le sujet du corps avec une ligne blanche
- Limiter la ligne de sujet à 50 caractères
- Capitaliser la ligne de sujet
- Ne pas terminer la ligne de sujet par un point
- Utiliser l’humeur impérative dans la ligne de sujet
- Envelopper le corps à 72 caractères
- Utiliser le corps pour expliquer quoi et pourquoi vs. comment
Par exemple:
Summarize changes in around 50 characters or lessMore detailed explanatory text, if necessary. Wrap it to about 72characters or so. In some contexts, the first line is treated as thesubject of the commit and the rest of the text as the body. Theblank line separating the summary from the body is critical (unlessyou omit the body entirely); various tools like `log`, `shortlog`and `rebase` can get confused if you run the two together.Explain the problem that this commit is solving. Focus on why youare making this change as opposed to how (the code explains that).Are there side effects or other unintuitive consequences of thischange? Here's the place to explain them.Further paragraphs come after blank lines. - Bullet points are okay, too - Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but conventions vary hereIf you use an issue tracker, put references to them at the bottom,like this:Resolves: #123See also: #456, #789
Séparer le sujet du corps avec une ligne blanche
D’après la page de manuel git commit
:
Bien que ce ne soit pas obligatoire, c’est une bonne idée de commencer le message commit avec une seule ligne courte (moins de 50 caractères) résumant le changement, suivie d’une ligne blanche puis d’une description plus approfondie. Le texte jusqu’à la première ligne vide dans un message de livraison est traité comme le titre de la livraison, et ce titre est utilisé dans tout Git. Par exemple, Git-format-patch(1) transforme un commit en email, et il utilise le titre sur la ligne Sujet et le reste du commit dans le corps.
Premièrement, tous les commits ne nécessitent pas à la fois un sujet et un corps. Parfois, une seule ligne suffit, surtout lorsque le changement est si simple qu’aucun autre contexte n’est nécessaire. Par exemple:
Fix typo in introduction to user guide
Rien de plus n’a besoin d’être dit ; si le lecteur se demande quelle était la coquille, il peut simplement jeter un coup d’oeil au changement lui-même, c’est-à-dire utiliser git show
ou git diff
ou git log -p
.
Si vous committez quelque chose comme ça en ligne de commande, il est facile d’utiliser l’option -m
à git commit
:
$ git commit -m"Fix typo in introduction to user guide"
Par contre, quand un commit mérite un peu d’explication et de contexte, vous devez écrire un corps. Par exemple:
Derezz the master control programMCP turned out to be evil and had become intent on world domination.This commit throws Tron's disc into MCP (causing its deresolution)and turns it back into a chess game.
Les messages de commit avec corps ne sont pas si faciles à écrire avec l’option -m
. Il est préférable d’écrire le message dans un éditeur de texte approprié. Si vous n’avez pas déjà un éditeur configuré pour être utilisé avec Git en ligne de commande, lisez cette section de Pro Git.
Dans tous les cas, la séparation du sujet et du corps est payante quand on parcourt le journal. Voici l’entrée de journal complète:
$ git logcommit 42e769bdf4894310333942ffc5a15151222a87beAuthor: Kevin Flynn <[email protected]>Date: Fri Jan 01 00:00:00 1982 -0200 Derezz the master control program MCP turned out to be evil and had become intent on world domination. This commit throws Tron's disc into MCP (causing its deresolution) and turns it back into a chess game.
Et maintenant git log --oneline
, qui imprime juste la ligne de sujet:
$ git log --oneline42e769 Derezz the master control program
Ou, git shortlog
, qui regroupe les commits par utilisateur, montrant à nouveau juste la ligne de sujet pour la concision:
$ git shortlogKevin Flynn (1): Derezz the master control programAlan Bradley (1): Introduce security program "Tron"Ed Dillinger (3): Rename chess program to "MCP" Modify chess program Upgrade chess programWalter Gibbs (1): Introduce protoype chess program
Il y a un certain nombre d’autres contextes dans Git où la distinction entre la ligne de sujet et le corps entre en jeu-mais aucun d’entre eux ne fonctionne correctement sans la ligne blanche entre les deux.
Limiter la ligne d’objet à 50 caractères
50 caractères n’est pas une limite stricte, juste une règle empirique. Garder les lignes d’objet à cette longueur garantit qu’elles sont lisibles, et oblige l’auteur à réfléchir un moment à la façon la plus concise d’expliquer ce qui se passe.
Conseil : Si vous avez du mal à résumer, vous pourriez commettre trop de changements à la fois. Efforcez-vous de commits atomiques (un sujet pour un post séparé).
L’interface utilisateur de GitHub est pleinement consciente de ces conventions. Elle vous avertira si vous dépassez la limite de 50 caractères :
Et tronquera toute ligne d’objet de plus de 72 caractères avec une ellipse :
Donc visez les 50 caractères, mais considérez 72 comme la limite stricte.
Capitalisez la ligne d’objet
C’est aussi simple que cela puisse paraître. Commencez toutes les lignes d’objet par une majuscule.
Par exemple:
- Accelerate to 88 miles per hour
A la place de:
- accelerate to 88 miles per hour
Ne terminez pas la ligne d’objet par un point
La ponctuation traînante est inutile dans les lignes d’objet. En outre, l’espace est précieux lorsque vous essayez de les garder à 50 caractères ou moins.
Exemple:
- Ouvrir les portes de la baie des capsules
A la place de:
- Ouvrir les portes de la baie des capsules.
Utiliser l’humeur impérative dans l’objet
L’humeur impérative signifie simplement « parlé ou écrit comme si on donnait un ordre ou une instruction ». Quelques exemples:
- Nettoie ta chambre
- Fermet la porte
- Porte la poubelle
Chacune des sept règles que vous lisez en ce moment est écrite à l’impératif (« Enveloppe le corps à 72 caractères », etc.).
L’impératif peut sembler un peu grossier ; c’est pourquoi nous ne l’utilisons pas souvent. Mais il est parfait pour les lignes d’objet des commit Git. L’une des raisons en est que Git lui-même utilise l’impératif chaque fois qu’il crée un commit en votre nom.
Par exemple, le message par défaut créé lors de l’utilisation de git merge
se lit:
Merge branch 'myfeature'
Et lors de l’utilisation de git revert
:
Revert "Add the thing with the stuff"This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.
Ou lorsque vous cliquez sur le bouton « Merge » sur une pull request GitHub:
Merge pull request #123 from someuser/somebranch
Donc, lorsque vous écrivez vos messages de commit à l’impératif, vous suivez les propres conventions intégrées de Git. Par exemple:
- Refactoriser le sous-système X pour plus de lisibilité
- Mettre à jour la documentation de démarrage
- Supprimer les méthodes dépréciées
- Relancer la version 1.0.0
Écrire de cette façon peut être un peu gênant au début. Nous sommes plus habitués à parler à l’indicatif, qui consiste à rapporter des faits. C’est pourquoi les messages de commit finissent souvent par se lire comme ceci :
- Correction d’un bug avec Y
- Modification du comportement de X
Et parfois les messages de commit sont écrits comme une description de leur contenu :
- Plus de corrections pour des trucs cassés
- De nouvelles méthodes d’API douces
Pour enlever toute confusion, voici une règle simple pour avoir raison à chaque fois.
Une ligne de sujet de commit Git correctement formée devrait toujours pouvoir compléter la phrase suivante :
- Si elle est appliquée, ce commit va votre ligne de sujet ici
Par exemple :
- Si appliqué, ce commit refactorera le sous-système X pour la lisibilité
- Si appliqué, ce commit mettra à jour la documentation de démarrage
- Si appliqué, ce commit supprimera les méthodes dépréciées
- Si appliqué, ce commit publiera la version 1.0.0
- Si appliqué, ce commit fusionnera la pull request #123 de l’utilisateur/branche
Notez comment cela ne fonctionne pas pour les autres formes non impératives :
- Si appliqué, ce commit corrigera un bug avec Y
- Si appliqué, ce commit changera le comportement de X
- Si appliqué, ce commit corrigera plus de choses cassées
- Si appliqué, ce commit sucrera de nouvelles méthodes API
Rappellez-vous : L’utilisation de l’impératif est importante uniquement dans la ligne d’objet. Vous pouvez relâcher cette restriction lorsque vous écrivez le corps.
Enveloppez le corps à 72 caractères
Git n’enveloppe jamais le texte automatiquement. Lorsque vous écrivez le corps d’un message de livraison, vous devez faire attention à sa marge droite, et envelopper le texte manuellement.
La recommandation est de le faire à 72 caractères, de sorte que Git ait beaucoup de place pour indenter le texte tout en gardant tout sous 80 caractères au total.
Un bon éditeur de texte peut aider ici. Il est facile de configurer Vim, par exemple, pour envelopper le texte à 72 caractères lorsque vous écrivez un commit Git. Traditionnellement, cependant, les IDE ont été terribles pour fournir un support intelligent pour l’enveloppement du texte dans les messages de commit (bien que dans les versions récentes, IntelliJ IDEA s’est finalement amélioré à ce sujet).
Utiliser le corps pour expliquer quoi et pourquoi vs. comment
Ce commit de Bitcoin Core est un excellent exemple d’explication de ce qui a changé et pourquoi :
commit eb0b56b19017ab5c16c745e6da39c53126924ed6Author: Pieter Wuille <[email protected]>Date: Fri Aug 1 22:57:55 2014 +0200 Simplify serialize.h's exception handling Remove the 'state' and 'exceptmask' from serialize.h's stream implementations, as well as related methods. As exceptmask always included 'failbit', and setstate was always called with bits = failbit, all it did was immediately raise an exception. Get rid of those variables, and replace the setstate with direct exception throwing (which also removes some dead code). As a result, good() is never reached after a failure (there are only 2 calls, one of which is in tests), and can just be replaced by !eof(). fail(), clear(n) and exceptions() are just never called. Delete them.
Jetez un coup d’œil au diff complet et pensez simplement au temps que l’auteur fait gagner à ses collègues et aux futurs committers en prenant le temps de fournir ce contexte ici et maintenant. S’il ne le faisait pas, il serait probablement perdu à jamais.
Dans la plupart des cas, vous pouvez laisser de côté les détails sur la façon dont un changement a été fait. Le code est généralement auto-explicatif à cet égard (et si le code est si complexe qu’il doit être expliqué en prose, c’est à cela que servent les commentaires de source). Concentrez-vous simplement sur la clarification des raisons pour lesquelles vous avez fait le changement en premier lieu – la façon dont les choses fonctionnaient avant le changement (et ce qui n’allait pas avec cela), la façon dont elles fonctionnent maintenant, et pourquoi vous avez décidé de le résoudre de la façon dont vous l’avez fait.
Le futur mainteneur qui vous remercie sera peut-être vous-même !
Tips
Apprenez à aimer la ligne de commande. Laissez l’IDE derrière.
Pour autant de raisons qu’il y a de sous-commandes Git, il est sage d’embrasser la ligne de commande. Git est follement puissant ; les IDE le sont aussi, mais chacun de manière différente. J’utilise un IDE tous les jours (IntelliJ IDEA) et j’en ai beaucoup utilisé d’autres (Eclipse), mais je n’ai jamais vu d’intégration d’IDE pour Git qui puisse commencer à égaler la facilité et la puissance de la ligne de commande (une fois que vous la connaissez).
Certaines fonctions d’IDE liées à Git sont inestimables, comme appeler git rm
lorsque vous supprimez un fichier, et faire les bonnes choses avec git
lorsque vous en renommez un. Là où tout s’écroule, c’est lorsque vous commencez à essayer de commiter, de fusionner, de rebaser ou de faire une analyse sophistiquée de l’historique à travers l’IDE.
Quand il s’agit de manier toute la puissance de Git, c’est la ligne de commande à fond.
N’oubliez pas que, que vous utilisiez Bash ou Zsh ou Powershell, il existe des scripts de complétion de tabulation qui enlèvent une grande partie de la douleur de se souvenir des sous-commandes et des commutateurs.
Lisez Pro Git
Le livre Pro Git est disponible en ligne gratuitement, et il est fantastique. Profitez-en !
Crédit image d’en-tête : xkcd
.