Voici le dix-huitième volet de la formation Git. Dans mon précédent article, nous avons vu en détail le renommage des branches. Aujourd’hui nous allons nous intéresser de plus près au rôle de ce mystérieux HEAD
que vous avez pu voir apparaître dans les logs.
Comprendre HEAD par la pratique
Lorsqu’on souhaite afficher la différence entre deux commits, on peut très bien utiliser la procédure suivante :
- Afficher les logs avec
git log
et les options qui vont bien. - Repérer les identifiants respectifs des commits que l’on souhaite comparer.
- Invoquer
git diff
en effectuant deux opérations successives de copier/coller sur ces identifiants.
Une autre manière de faire – et qui est bien plus commode pour les commits relativement récents – utilise la référence HEAD
.
Prenons un dépôt Git simple avec un historique linéaire sans la moindre branche :
$ cd ~/formation-git/atelier-23/ $ git log --oneline b71f6b2 (HEAD -> master) Renommage du fichier. cbeca14 Ajout du fichier Cartes. 7def037 Ajout d'une destination. 9159976 Ajout du fichier Entretien. 4220c4c Ajout du fichier Roadtrip.
Vous connaissez tous le fameux petit symbole VOUS ÊTES ICI
sur les plans affichés dans le centre historique des villes et des grands centres commerciaux ? Ou alors l’icône qui symbolise votre emplacement actuel dans les applications de géolocalisation de votre smartphone ? Le rôle de HEAD
dans Git, c’est exactement cela : vous montrer votre emplacement actuel dans l’historique.
Admettons que dans mon dépôt Git, je souhaite afficher la différence entre l’avant-dernier et le dernier commit. Dans ce cas, j’effectue un copier/coller des identifiants respectifs, et j’invoque git diff
comme ceci :
$ git diff cbeca14 b71f6b2 diff --git a/Entretien.md b/Maintenance.md similarity index 100% rename from Entretien.md rename to Maintenance.md
Notez bien que j’écris d’abord l’identifiant du commit parent.
Alternativement, je pourrais utiliser la syntaxe suivante :
$ git diff HEAD~1 HEAD diff --git a/Entretien.md b/Maintenance.md similarity index 100% rename from Entretien.md rename to Maintenance.md
HEAD
est la référence qui désigne le commit actuel.HEAD~1
représente le premier parent du commit actuel.
Admettons maintenant que je veuille afficher la différence entre l’avant-dernier commit et son parent. En utilisant les identifiants respectifs, voilà ce que j’obtiendrais :
$ git diff 7def037 cbeca14 diff --git a/Cartes.md b/Cartes.md new file mode 100644 index 0000000..a6e35b6 --- /dev/null +++ b/Cartes.md @@ -0,0 +1,9 @@ +# Cartes routières + +- [ ] France + +- [ ] Italie + +- [ ] Suisse + +- [ ] Autriche
Et en utilisant HEAD
:
$ git diff HEAD~2 HEAD~1 diff --git a/Cartes.md b/Cartes.md new file mode 100644 index 0000000..a6e35b6 --- /dev/null +++ b/Cartes.md @@ -0,0 +1,9 @@ +# Cartes routières + +- [ ] France + +- [ ] Italie + +- [ ] Suisse + +- [ ] Autriche
Vous l’aurez compris : lorsqu’on écrit HEAD~n
, le nombre n
après le symbole tilde ~
symbolise le n
-ième ancêtre du commit actuel.
Mais ce n’est pas tout. Rappelez-vous que lorsque nous fusionnons deux branches avec un merge commit, ce dernier se distingue par le fait qu’il a deux commits parents. Comment faire alors ?
Pour ne pas nous perdre dans les méandres soporifiques de la théorie, cherchons tout de suite un exemple pratique :
$ cd ~/formation-git/atelier-16 $ git log --oneline --graph --all * 403fb57 (HEAD -> master) Merge branch 'hello-figlet'. |\ | * d0c718c (hello-figlet) Message en lettres ASCII. * | 36bfb46 (hello-cow) Message avec une vache qui parle. |/ * 797fe52 Commit initial.
- Concrètement, le commit actuel
403fb57
est le produit de la fusion des deux commits parents36bfb46
etd0c718c
. - Avec la référence
HEAD
, nous pourrons désigner le premier parent (36bfb46
) parHEAD^1
et le deuxième parent (d0c718c
) parHEAD^2
.
Si j’essaie de mettre en pratique cette manière de faire, je devrais obtenir le même résultat pour les deux commandes suivantes :
$ git diff d0c718c 403fb57 ... $ git diff HEAD^2 HEAD ...
Est-ce que je pourrais aller plus loin ? Oui, en combinant les deux écritures :
HEAD^1~1
est le premier ancêtre du premier parent.HEAD^1~2
est le deuxième ancêtre du premier parent.HEAD^2~1
est le premier ancêtre du deuxième parent.HEAD^2~2
est le deuxième ancêtre du deuxième parent.- Etc.
Là aussi, je vais tester ce principe dans la pratique en vérifiant si j’obtiens un résultat identique pour les commandes suivantes :
$ git diff 797fe52 36bfb46 ... $ git diff HEAD^1~1 HEAD^1 ...
Ou encore :
$ git diff 797fe52 d0c718c ... $ git diff HEAD^2~1 HEAD^2 ...
Vous l’aurez remarqué : dans notre exemple, le commit 797fe52
peut être référence par HEAD^1~1
aussi bien que par HEAD^2~2
. Comme quoi différents chemins mènent à Saint-Bauzille-de-Putois.
Exercice
Rendez-vous dans le répertoire ~/formation-git/atelier-15/hello
et affichez l’historique complet du dépôt :
$ cd ~/formation-git/atelier-14/hello/ $ git log --oneline --graph --all * b2139e1 (HEAD -> master) Merge branch 'hello-figlet'. |\ | * 8db1b22 Premier jet avec des majuscules ASCII. * | 5a7dd1d Merge branch 'hello-cow'. |\ \ | * | 477d1a0 Implémentation d'une vache fatiguée. | * | d268724 Premier jet de la vache qui dit bonjour. | |/ * / 89211a3 Peaufinage du script initial. |/ * bebe769 Commit initial.
La commande git rev-parse --short
permet d’afficher l’identifiant correspondant à la référence avec HEAD
:
$ git rev-parse --short HEAD
b2139e1
$ git rev-parse --short HEAD^1
5a7dd1d
...
- Essayez de référencer tous les commits du dépôt en utilisant l’écriture avec
HEAD
. - Trouvez les trois écritures possibles pour le commit initial
bebe769
. - Prenez un cachet d’aspirine. :o)
Lire la suite : Retour vers le commit
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.
0 commentaire