1 points par GN⁺ 5 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Conventional Commits tente de donner du sens aux messages de commit avec le format <type>[optional scope]: <description>, mais met en avant le type de changement et relègue le périmètre en option, repoussant ainsi l’information réellement utile pour l’exploration
  • Les contributeurs, débogueurs et équipes de réponse aux incidents cherchent dans le log des commits les zones de code touchées par un changement, et comme un bug peut apparaître dans n’importe quel type de modification, le scope est plus important que le type
  • Avec fix(compiler): prevent namespaced SVG <style> elements from being stripped, la description suffit déjà à indiquer qu’il s’agit d’un correctif de bug, et avec refactor(core): Update webmcp support to use document.modelContext, un même commit peut relever à la fois de la correction, du refactoring et de l’ajout de fonctionnalité, ce qui rend le type redondant et limité
  • La génération automatique du CHANGELOG et la décision d’augmenter une version sémantique posent problème, car les lecteurs du log des commits et du journal des changements ne sont pas les mêmes, et le résultat peut diverger à cause des revert, des ruptures de compatibilité accidentelles ou de corrections ultérieures de ces ruptures
  • Les messages de commit à préfixe de scope montrent d’abord l’objet du changement, et pour les conditions de build ou de déploiement, il vaut mieux se baser sur les fichiers modifiés via git diff que sur le type indiqué dans le titre

Des priorités erronées

  • Conventional Commits a pour objectif de donner du sens aux messages de commit afin d’aider les développeurs et les utilisateurs finaux à comprendre les changements
<type>[optional scope]: <description>

[optional body]

[optional footer(s)]
  • La ligne de titre se compose d’un <type> comme fix, feat, chore, docs ou refactor, d’un scope optionnel et d’une description
  • Son défaut fondamental est de donner la priorité au type de changement plutôt qu’au scope, c’est-à-dire à la cible réelle du changement
  • Le fait que le scope soit optionnel permet de faire disparaître l’information la plus importante d’un commit, et placer le type tout au début du titre inverse les priorités

Pourquoi le scope est plus important que le type

  • Les contributeurs lisent le log des commits pour repérer les changements depuis leur dernière contribution, le flux global du projet et les commits susceptibles d’entrer en conflit avec leur travail en cours lors d’un pull ou d’un rebase
  • Les débogueurs cherchent les changements qui ont touché les zones liées au composant où le bug s’est manifesté, et comme un bug peut apparaître dans n’importe quel type de modification, l’information de type n’aide pas
  • Les équipes de réponse aux incidents parcourent le log autour du moment de la panne pour trouver la zone en cause ; si une hausse des erreurs sur l’API entrante coïncide avec un commit de scope auth, cela devient un candidat crédible
  • Pour les personnes qui lisent le log des commits, l’information importante n’est pas la nature du changement, mais la zone qu’il a touchée

La redondance et les limites du type

  • fix(compiler): prevent namespaced SVG <style> elements from being stripped indique déjà, par la seule description, qu’il s’agit d’une correction de bug, ce qui rend le type fix redondant
  • L’espace disponible dans la ligne de titre d’un commit étant limité, consacrer des caractères à un type déjà déductible de la description n’aide pas
  • refactor(core): Update webmcp support to use document.modelContext met à jour la fonctionnalité webmcp du composant core afin de prendre en charge à la fois document.modelContext et navigator.modelContext
  • Ce changement peut être vu simultanément comme une correction, un refactoring et une nouvelle fonctionnalité, alors que l’information vraiment importante est qu’il concerne le composant core/webmcp

Les limites de la promesse d’automatisation

  • L’idée de générer automatiquement un CHANGELOG à partir des commits avec des outils comme git-cliff ou conventional-changelog se heurte au fait que les lecteurs du log des commits et du journal des changements ne sont pas les mêmes
  • Un CHANGELOG s’adresse aux utilisateurs et se concentre sur la compréhension des différences fonctionnelles et métier entre deux versions
  • Le log des commits s’adresse aux développeurs et se concentre sur la façon dont la base de code évolue dans le temps ainsi que sur son flux du point de vue des scopes
  • Dans un projet d’une complexité au moins intermédiaire, une fonctionnalité significative arrive souvent en plusieurs commits ; pour les développeurs, le processus d’implémentation est utile, mais pour l’utilisateur final, seule la nouvelle fonctionnalité compte
  • Les commits de revert sont importants pour les développeurs dans le déroulé du log, mais pour l’utilisateur final, une modification annulée équivaut à une modification qui n’a jamais existé
  • L’augmentation de version sémantique fondée sur le type du commit peut conduire à augmenter une version majeure alors qu’un changement cassant a été revert, à incrémenter à tort en minor/patch parce que la rupture n’a été détectée que plus tard, ou à juger un changement cassant alors qu’une série de commits ultérieurs a supprimé cette rupture
  • On peut corriger l’historique avec un rebase dans de telles situations, mais le workflow peut l’empêcher ou le fragiliser, et cela réduit la fiabilité du récit porté par le log des commits
  • Déclencher les processus de build ou de déploiement à partir du type dans le titre d’un commit permet aussi de contourner les outils automatiques, par exemple avec un commit intitulé docs: fix typos qui introduit en réalité une faille dans le sous-système d’authentification
  • Pour les conditions de build et de déploiement, il vaut mieux identifier les fichiers modifiés via git diff que se fier au titre du commit

Problèmes d’adoption et alternative

  • Conventional Commits demande de définir un ensemble de types propre à chaque projet, mais beaucoup de projets reprennent simplement les types par défaut de commitlint, qui peuvent mal correspondre aux spécificités du projet
  • La spécification Conventional Commits ne définit en pratique que fix et feat, et laisse les autres types à la discrétion du projet
  • En environnement d’entreprise, des exigences de gestion du changement et d’audit imposent parfois d’inclure un numéro de ticket dans tous les messages de commit ; si <scope> sert à y mettre ce numéro, on perd une métadonnée utile
  • Linux, FreeBSD, Git, Go, NixOS et Node.js utilisent des messages de commit à préfixe de scope adaptés à leur projet
  • Dans le noyau Linux, le sous-système constitue un scope naturel ; dans le projet Go, c’est le chemin du package ; dans une architecture en microservices, ce sera le nom du microservice
  • scopedcommits.com défend un retour à un format de message de commit centré sur le scope et une séparation entre génération du CHANGELOG et gestion du log des commits
  • Les avantages supposés de Conventional Commits ne se sont pas traduits en bénéfices réels, et sa popularité dans l’open source ainsi que la tendance des IA à le choisir par défaut ont favorisé la diffusion de messages de commit mêlant des antipatterns

1 commentaires

 
GN⁺ 5 시간 전
Avis sur Lobste.rs
  • Je suis content de voir un texte qui formule une critique des conventional commits avec des arguments plutôt qu’un simple rejet instinctif.
    Je n’avais pas vraiment réfléchi en profondeur à pourquoi je n’aimais pas ça, et je me demandais si ce n’était pas lié au fait que je l’associe au code généré par les LLM. Je déteste surtout chore: et j’aimerais qu’on évite de réinventer la notation hongroise. Ça n’aurait jamais dû être créé au départ.

    • En particulier, chore: n’existe même plus dans le guide de style de commit Angular et a été absorbé par build:, sans doute parce qu’ils se sont rendu compte que c’était trop vague.
      Même à l’époque où il figurait dans le style Angular, la description de chore: indiquait des usages assez précis, mais dans certains projets open source, on a l’impression qu’il est collé par ambiance à des tâches qui ressemblent littéralement à des corvées
  • Je n’aime pas spécialement les conventional commits, mais l’alternative proposée semble passer à côté de la raison pour laquelle le scope est optionnel.
    Dans les petits projets sans modules bien distincts, la notion de « scope » n’est pas très utile. Une pratique utile que les deux camps omettent, c’est d’ajouter un numéro d’issue ou de ticket dans le titre du commit : ça donne plus facilement du contexte sur le changement et c’est particulièrement utile pendant la revue de code. En revanche, je n’aime pas l’idée de rendre le numéro de ticket obligatoire, parce que ça finit par produire des tickets inutiles pour des changements mineurs. Mais si une modif traite un bug ou une tâche précise, elle devrait être liée à ce bug ou à cette tâche.

    • S’il n’y a pas besoin de scope, il suffit de l’omettre.
      C’est toujours mieux qu’un « type » de commit redondant qui devrait déjà ressortir rien qu’à la lecture de la ligne de titre
    • Dans l’idéal, il ne devrait y avoir aucun style de commit imposé, et il faudrait simplement utiliser la formulation adaptée à chaque commit.
      Si un changement correspond clairement à un ticket, on peut faire un commit avec « numéro de ticket » ; sinon, on peut employer une autre forme. Certains changements collent bien à un type mais moins à un scope, et inversement, donc on peut aussi mélanger scoped commits et conventional commits
  • J’ai envie de dire : « n’utilisez pas une police à chasse fixe dans du texte en paragraphe ».
    Cela dit, je suis globalement d’accord avec la prémisse de l’article

  • Même si les messages de commit ne sont pas terribles, pour se faire une idée de l’ampleur d’un changement, je recommande d’utiliser souvent git log --name-only ou git log --stat.
    Voir les noms de fichiers aide beaucoup à comprendre ce qui a changé sans avoir à ouvrir chaque commit un par un

  • Une approche que j’aime vraiment, c’est d’imposer le style conventional commit sur les titres de PR.
    Les titres de PR peuvent être modifiés par les maintainers même après la fusion, ça évite de réécrire l’historique des commits, et avec des outils comme release-drafter, on peut automatiser un changelog pertinent dans les releases GitHub. Ça offre une granularité adaptée aux parties prenantes évoquées par l’auteur, en séparant fonctionnalités, corrections et ruptures de compatibilité, tout en gérant automatiquement un semver raisonnable pour le prochain brouillon de release GitHub.
    L’auteur a raison de dire qu’un composant comme parse-lib ne devrait pas être optionnel, et je suis aussi d’accord sur le fait qu’imposer les conventional commits peut décourager les nouvelles contributions. Mais les alternatives ne sont pas forcément meilleures.
    Cela dit, un identifiant de rupture de compatibilité comme fix!(parse-lib): Don't leave sparse holes when parsing JSON arrays transmet quand même pas mal d’informations. On comprend qu’il s’agit d’un correctif sur un composant précis, qu’il s’accompagne inévitablement d’une rupture de compatibilité, et qu’il porte un sens du type incrémentation semver mineure. Ce genre de chose peut très bien être utilisé dans un titre de PR

  • Je reconnais avoir trop misé sur les conventional commits comme moyen d’encourager une discipline des commits, au point d’en faire une habitude.
    Aujourd’hui, ça me semble souvent limité et arbitraire. Sur certains projets, sans même savoir si c’était la vraie convention, je me suis rapproché d’un style Linux/Go/Node, et dans des monorepos avec beaucoup de configuration, il paraissait plus naturel d’écrire [service]: [what changed] que d’inventer de force un type. À l’avenir, j’ai envie d’expérimenter davantage mon style personnel de commit en me demandant surtout ce qui semble utile, plutôt que de me conformer à des règles strictes, et les scoped commits me paraissent être un bon point de départ

  • chore(lobsters): add my 2 cents on conventionals commits [JIRA-69420]
    Je suis d’accord avec presque tout, mais je diverge sur un point : l’idée que cela « montre aux contributeurs un historique révisionniste qui réduit la fiabilité de l’histoire racontée par le journal des commits ». L’auteur semble parler principalement des branches publiques, et dans ce cas c’est un conseil raisonnable. Mais cela ne devrait pas s’appliquer aux branches privées. Il faut surtout que la personne qui relit le changement final — le maintainer ou moi dans dix ans — puisse le comprendre facilement ; il n’est pas nécessaire de conserver un cheminement de pensée incohérent, ni pire encore, une série de commits address review

  • La réponse à « pourquoi le scope est-il optionnel ? » est que, dans les petits projets, le projet entier est simplement le scope.
    Je suis d’accord pour dire que le « type » du commit n’est pas très utile, mais je ne vois pas non plus une énorme différence entre scoped commits et conventional commits. Les scoped commits, c’est juste du conventional sans le « type », et distinguer fix, feat, refactor et chore n’est pas forcément absurde.
    Si tout le monde se contente de reprendre les valeurs par défaut de commitlint, est-ce qu’il ne suffirait pas plutôt de faire en sorte que les gens les maîtrisent mieux ?