Les syntaxes de révisions Git
On utilise les syntaxes de révisions souvent sans s’en apercevoir, explicitement ou implicitement. Lorsqu’on désigne une branche pour en changer, pour la fusionner, la rebaser. Lorsqu’on désigne un ou plusieurs commits pour les analyser, les modifier…
Vous l’aurez compris, les syntaxes de révisions servent à cibler un emplacement spécifique de l’historique ou un intervalle de commits. Certaines de ces syntaxes ont des fonctions assez techniques, utiles pour des scripts par exemple. Nous avons effectué une petite sélection des syntaxes qui nous semblent utiles pour un usage quotidien ou occasionnel.
Syntaxes “courantes”
Parmi les syntaxes qu’on utilise parfois sans y penser, on trouve :
- les identifiants des objets/commits sous la forme canonique (sha/abbrev-sha) ;
- Les noms de branches, de tags ;
- HEAD (notre emplacement actuel, souvent utilisé comme valeur par défaut quand aucune valeur n’est renseignée).
Quand vous changez des branches (switch
), affichez le contenu d’un commit (show
), que vous faites une fusion (merge
) vous associez aux commandes des syntaxes de révisions, vous désignez une branche (donc indirectement un commit) ou un commit explicite.
Voici quelques exemples :
# "dev" est la syntaxe désignant indirectement le dernier commit de la branche
git switch dev
# On utilise les syntaxes de révisions "HEAD" et "dev"
git rebase HEAD dev
# "ef3149f60" est l’identifiant du commit dont on souhaite afficher le contenu
git show ef3149f60
# Affiche les 5 derniers commits jusqu’au commit "ef3149f60"
git log ef3149f60 -5
Parmi les nombreuses autres syntaxes existantes, certaines valent la peine qu’on s’y intéresse pour un usage occasionnel, voire régulier.
N-ième ancêtre en ligne “directe”
Il s’agit de la syntaxe à base de ~
, suivie d’une valeur numérique : ~N
. On désigne ainsi le commit N
crans en arrière depuis la base donnée.
gitGraph commit id: "main~0" commit id: "main~1" commit id: "main~2" commit id: "main~3"
L’avantage de cette syntaxe est qu’elle fonctionne depuis n’importe quelle autre syntaxe : HEAD~1
, develop~2
, <sha1>~1
…
Voici quelques exemples :
HEAD~1 # L’avant dernier commit par rapport à notre emplacement actuel
HEAD~2 # L’avant-avant dernier commit
dev~1 # L’avant dernier commit sur la branche "dev"
f59038c~1 # Le commit précédent celui ayant pour identifiant "f59038c"
Exemple : défaire le dernier commit et préserver ses modifications
Pour défaire le dernier commit tout en conservant ce qu’il contient au niveau du stage, on peut utiliser la commande reset et la syntaxe de révision à base de ~
:
git reset --soft HEAD~1
De nombreux exemples similaires sont décrits dans notre série “Annuler, défaire, corriger”.
Reflog
Le reflog, dont le fonctionnement est expliqué dans cet autre article, utilise une syntaxe de révision qui lui est spécifique, sur le format @{<indice numérique>}
. On peut l’utiliser, par exemple, pour défaire une fusion ou un rebase :
git reset --keep <branche-ciblée>@{1}
# Exemple : git reset --keep main@{1}
# Fonctionne également au format "git reset --keep @{1}"
# quand on est sur la bonne branche
L’avant-dernière branche active
La syntaxe @{-1}
désigne l’avant dernière branche active (ou plus exactement l’avant dernier commit ciblé par un checkout). L’indice numérique peut varier. Ainsi @{-2}
désigne l’avant-avant-dernière branche active.
Cette notation bénéficie d’un raccourci qui n’est pas décrit dans la documentation mais qui s’avère bien pratique, surtout pour les utilisateurs·rices du terminal qui pratiquent le cd -
: la notation -
qui équivaut à @{-1}
.
Quelques cas pratiques
Avec cette notation on peut :
- revenir sur la branche précédente en faisant un
git switch -
; - fusionner la branche précédente avec un
git merge -
; - mettre à jour la branche actuelle sur la branche précédente avec un
git rebase -
.
À vous de voir quels autres usages pour pouvez en faire !
Intervalles
Vous souhaitez afficher l’historique entre 2 commits ? Aucun problème, il suffit de désigner l’intervalle de la manière suivante :
git log <commit-1>..<commit-2>
Cette syntaxe va lister l’ensemble des commits jusqu’à commit-2
en excluant ceux allant jusqu’à commit-1
(ce dernier étant également exclu).
En partant de l’exemple ci-dessous, la syntaxe c1..c5
prendrait en considération les commits c2
, c3
, c4
et c5
.
gitGraph commit id: "c0" commit id: "c1" commit id: "c2" type: HIGHLIGHT commit id: "c3" type: HIGHLIGHT commit id: "c4" type: HIGHLIGHT commit id: "c5" type: HIGHLIGHT commit id: "c6" commit id: "c7"
L’astuce pour intégrer le commit-1
à l’intervalle est de partir un cran avant lui :
git log <commit-1>~1..<commit-2>
Obtenir la version d’un fichier dans un commit donné
Visualiser la version d’un fichier
On peut combiner les syntaxes de révisions avec le suffixe :<chemin>
pour afficher le contenu d’un fichier au moment d’un commit particulier.
Par exemple, en faisant un
git show HEAD~1:README.md
on obtient la version du fichier README.md
(son contenu) à l’état de l’avant dernier commit.
Si on fait un
git show dev:README.md
on obtient le contenu du fichier dans sa version actuelle sur la branche dev
.
Appliquer la version d’un fichier dans l’espace de travail
On peut aussi aller plus loin en récupérant/appliquant dans notre espace de travail la version d’un fichier issue d’une autre branche ou d’un autre commit. Par exemple, si je veux récupérer un fichier de configuration depuis la branche dev
, je peux faire :
git checkout dev:app/config.yml
Dernier commit dont le message correspond à l’expression
On peut chercher le commit le plus récent (toute branche confondue) dont le message contient un texte donné (ou correspond à l’expression régulière passée) :
git show :/setup.*server
Si on souhaite préciser la référence à laquelle le commit doit être rattaché (par exemple une branche donnée), on devra préciser cette référence et utiliser une syntaxe légèrement différente :
git show dev^{/setup.*server}
Attention, Git n’affiche pas de message si aucune référence n’est trouvée
Raccourci vers la branche distante associée
Git distingue la branche depuis laquelle on reçoit les mises à jour (via un pull) de la branches vers laquelle on partage (push). Il nous permet en effet d’envoyer vers une branche b1 et de récupérer depuis une branche b2. En pratique, on a toujours une branche b1 qui sert aussi bien au pull qu’au push.
Ceci sert à introduire les syntaxes de révisions suivantes :
@{u}
ou@{upstream}
qui désigne la branche distante rattachée à notre branche locale et depuis laquelle on pull ;@{push}
qui désigne la branche distante rattachée à notre branche locale et vers laquelle on push.
Ces syntaxes peuvent être pratiques pour analyser les commits à récuperer ou à envoyer.
Vérifier ce qu’on s’apprête à pusher
Pour obtenir la liste des commits qu’on s’apprête à partager / pusher, on peut faire un :
git lg @{push}..
Cette syntaxe mêle deux syntaxes : la syntaxe d’intervalle et la syntaxe de référence à la branche distante.
NB : l’alias utilisé ici, lg
, correspond au log amélioré cité plus haut.
Vérifier ce qu’on s’apprête à récupérer
On peut obtenir la liste des commits qu’on s’apprête à récupérer et à appliquer depuis la branche distante en faisant un :
git fetch # D’abord, on voit ce qui a été publié sur le distant
git lg ..@{u} # Ensuite on liste les commits
La aussi, on mêle deux syntaxes de révisions : la syntaxe d’intervalle et la syntaxe de branche distante.
Vérifier la correspondance d’une syntaxe
Si vous avez un doute sur le périmètre de commits couvert par une syntaxe, vous pouvez en obtenir la liste complète à l’aide de la commande rev-parse
:
> git rev-parse f59038c~1
5d376dadea4094b852e9a40bb8a2e72df8c987f4 # On obtient l’identifiant du commit ciblé
Les autres syntaxes
Il existe encore d’autres syntaxes que nous considérons moins pertinentes pour un usage direct.
@
qui, seul, vaut comme alias àHEAD
<ref>^2
qui désigne le 2e parent du commit désigné (par exempleHEAD^2
pour désigner le dernier commit de la branche fusionnée)- les révisions par date, par exemple
@{yesterday}
,dev@{2025-02-12 18:30:00}
… - …
Si vous avez d’autres cas pratiques et syntaxes usuelles que vous souhaitez nous partager, n’hésitez pas à nous le signaler.
Vous pouvez également retrouver le détail de toutes les syntaxes en regardant la page du manuel associée (git help revisions
), disponible également en ligne.
Vous pouvez aussi regarder le programme de notre formation "Comprendre Git" ou nous poser vos questions sur notre forum discord.