Blame : suivi de la dernière modification de chaque ligne d’un fichier
La commande git blame permet d’afficher pour chaque ligne d’un fichier quelle fut la dernière personne à l’avoir modifiée et à quelle date. Mais attention, elle n’indique pas quelle a été la modification et peut se révéler être un mauvais indicateur si on l’interprète mal. J’avais à ce titre réalisé une petite vidéo pour expliquer pourquoi priviligier des alternatives telle que la recherche avec le log.
Quelles données fournies ?
Voici un exemple de ce qu’affiche la commande git blame :
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 1) import { ApiMode, Widgets } from '@payment/widgets'
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 2) import { number, string } from 'prop-types'
54e5cda820 (Ada Lovelace 2023-11-20 14:10:36 +0100 3) import { useEffect } from 'react'
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 4)
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 5) import './PaymentWidget.css'
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 6)
158b074c01 (Ada Lovelace 2023-10-19 21:44:37 +0200 7) const WIDGET_ID = 'payment-widget'
158b074c01 (Ada Lovelace 2023-10-19 21:44:37 +0200 8)
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 10) export default function PaymentWidget({ merchantId }) {
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 11) useEffect(() => {
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 12) const mode = process.env.NODE_ENV === 'production' ? 'LIVE' : 'TEST'
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 13) const widgets = Widgets.initialize(merchantId, ApiMode[mode])
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 14)
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 15) widgets.add(Widgets.PaymentPlans, {
158b074c01 (Ada Lovelace 2023-10-19 21:44:37 +0200 16) container: `#${WIDGET_ID}`,
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 17) purchaseAmount: cents,
72ee696146 (Ada Lovelace 2023-10-30 12:29:26 +0100 18) locale: 'fr',
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 19) })
72ee696146 (Ada Lovelace 2023-10-30 12:29:26 +0100 20) }, [merchantId, cents])
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 21)
72ee696146 (Ada Lovelace 2023-10-30 12:29:26 +0100 22) return <div style={\{ zoom: 0.9, maxWidth: 'max-content' \}} id={WIDGET_ID} />
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 23) }
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 24) PaymentWidget.propTypes = {
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 25) merchantId: string.isRequired,
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 26) cents: number.isRequired,
e5748ec3eb (Charles Babbage 2021-05-10 13:58:58 +0200 27) }
La lecture n’est pas toujours évidente selon la largeur d’écran. Certains outils permettent toutefois de faciliter l’exploitation de la commande. C’est le cas par exemple dans l’éditeur VSCode : l’information fournie au survol est interprétée de blame.
Que voit-on ici ?
- La première colonne correspond à l’identifiant du dernier commit ayant modifié la ligne ;
- La seconde donne l’identité du commiter et l’horodatage du commit ;
- Viennent ensuite le numéro de ligne et la ligne dans son état actuel.
Affiner l’affichage
On peut choisir différentes options pour obtenir un affichage plus digeste selon notre contexte. On peut par exemple :
- préciser l’intervalle des lignes à analyser dans un fichier :
git blame -L 10,23 chemin-du-fichier; - retirer de l’affichage les informations d’auteur et de date :
git blame -s; - préciser le format de date :
git blame --date=format-local:"%d/%M/%Y"; - restreindre l’affichage aux commits vieux de 3 semaines et plus :
git blame --since=3.weeks chemin-de-fichier; - restreindre l’affichage aux commits vieux de moins de 2 jours :
git blame --until=2.days chemin-de-fichier; - et d’autres options pour des cas d’usage moins courants que je ne détaillerai pas ici.
Blame tuning
On peut pousser la personnalisation de l’affichage jusqu’à demander une coloration spéciale selon l’ancienneté des commits. Ceci n’est valable que dans les terminaux qui supportent la coloration.
Voici un exemple de configuration :
# On active la coloration en demandant la mise en évidence des commits les plus récents
git config --global blame.coloring highlightRecent
# On spécifie les couleurs selon l'âge des commits
git config --global color.blame.highlightRecent "237, 20 month ago, 238, 19 month ago, 239, 18 month ago, 240, 17 month ago, 241, 16 month ago, 242, 15 month ago, 243, 14 month ago, 244, 13 month ago, 245, 12 month ago, 246, 11 month ago, 247, 10 month ago, 248, 9 month ago, 249, 8 month ago, 250, 7 month ago, 251, 6 month ago, 252, 5 month ago, 253, 4 month ago, 254, 3 month ago, 231, 2 month ago, 230, 1 month ago, 229, 3 weeks ago, 228, 2 weeks ago, 227, 1 week ago, 226"
Pourquoi l’information donnée par blame peut-être erronée ?
Prenons un exemple à partir de l’affichage précédent. La ligne 10 représente la définition d’une fonction. Admettons que son état actuel soit défaillant : il manque un paramètre cents. On s’attend à la ligne suivante :
export default function PaymentWidget({ merchantId, cents }) {
La lecture naïve de blame pourrait nous faire croire que Charles Babbage serait l’auteur de cette erreur. La commande ne nous renseigne pourtant pas sur la modification qu’il a effectué sur la ligne. Il se peut qu’il ait modifié autre chose. Dans notre exemple, c’est le cas. Charles a passé un outil de nettoyage du code qui a simplement retiré un espace en fin de ligne. Il n’est donc pas l’auteur de l’erreur.
Vous pouvez aussi regarder le programme de notre formation "Comprendre Git" ou nous poser vos questions sur notre forum discord.
Comment repérer plus finement l’origine de l’erreur
Avant toute chose, cette démarche ne devrait pas être entamée avec pour objet de punir l’auteur d’un bug. Dans le cas contraire, peut-être serait-il utile de revoir votre méthode de management 😉.
Revenons à Git : il propose une commande permettant de suivre les évolutions au sein d’un fichier, au sein d’une méthode/function ou en définissant l’intervalle des lignes qui nous intéresse. Je privilégie généralement cette seconde option que je trouve plus passe-partout. Cette commande, vous la connaissez probablement déjà, c’est
git lgmais avec une option particulière :-L.Pour notre cas d’exemple, nous pouvons analyser les lignes entourant la définition de notre déclaration de fonction :
Je le reprécise : cette option de commande ne permet de cibler qu’un fichier à la fois.
Je ne m’étends pas sur le sujet ici. Nous avons un article qui explique plus en détail la manière de procéder : git log : qui suis-je ? D’où viens-je ? Où vais-je ?.