Git HEAD : où ai-je la tête ?
Par Maxime Bréhin • Publié le 27 mai 2022 • 3 min

Comment savoir où nous sommes dans notre historique Git ? Sur quelle branche ? Dans quel état de notre projet ? C’est le rôle de HEAD : je ne vais nulle part sans ma tête ! Laisse-moi t’expliquer ce fondamental de Git.

Cet article fait partie de notre série sur le glossaire Git.

Tu préfères une vidéo ?

Si tu es du genre à préférer regarder que lire pour apprendre, on a pensé à toi :

Où tu iras j’irai 🎶

On considère le plus souvent HEAD comme un pointeur sur le dernier commit de la branche courante (ce qu’on appelle aussi la tête de branche). C’est généralement le cas, mais pas tout le temps.

HEAD est bien un pointeur, une référence vers un emplacement donné de notre historique (un commit si tu préfères). Il a deux fonctions principales :

  • nous repérer dans notre historique (le « Vous êtes ici » du GPS) ;
  • définir l’endroit depuis lequel nous produisons un commit.

Son comportement nominal est de « suivre » une étiquette de branche ou, pour être plus précis, de nous indiquer quelle est la branche active, définissant ainsi l’état de notre espace de travail, l’emplacement (le commit) qui servira de parent à notre prochain commit et la branche qui devra bouger.

Note : le terme « étiquette de branche » ne te dit rien ? Pas de panique, je t’explique ça dans un prochain article. Si tu as peur de le manquer, n’hésite pas à t’abonner à notre newsletter.

Sous le capot

Une petite explication technique t’aidera peut-être.

HEAD est représenté par le fichier .git/HEAD. Si on regarde son contenu, on trouvera toujours une seule ligne dont le format sera le plus souvent celui-ci :

ref: refs/heads/nom-de-branche

En d’autre termes, il contient généralement une référence à la branche courante. En fait, c’est justement parce qu’il contient la référence d’une branche, que celle-ci est considérée comme la branche courante / active !

Tu peux observer son comportement si tu demandes à Git de basculer sur une autre branche :

git switch autre-branche

Tu verras alors le fichier .git/HEAD pointer vers cette autre branche :

ref: refs/heads/autre-branche

Si on pousse un peu et qu’on crée un commit depuis cet emplacement, on verra que cette référence n’aura pas changé, HEAD pointera toujours sur autre-branche. C’est la valeur de cette étiquette de branche qui aura bougé (seulement parce qu’elle était désignée active par HEAD).

Une référence souvent implicite

De nombreuses commandes utilisent HEAD comme valeur par défaut pour marquer un emplacement à analyser. C’est le cas de git show qui, sans référence explicite, utilisera HEAD par défaut et affichera le commit « courant ».

Il en va de même pour git log lorsqu’on ne spécifie pas de syntaxe de révision qui t’affichera tout l’historique des commits jusqu’à HEAD.

Repérer HEAD dans le log

Du coup si HEAD est un indicateur précieux de notre emplacement courant, il semble pertinent de le repérer dans notre historique. C’est l’objectif de l’option --decorate de la commande log. Mais tant qu’à faire, autant utiliser un alias sympathique qui gère correctement l’affichage de notre historique (comme je l’expliquais dans cet autre article) :

git config --global alias.lg "log --graph --date=relative --pretty=tformat:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ad)%Creset'"

Log arborescent avec commits mono-lignes et infos utiles (auteur, date, branches, HEAD)

On obtient alors un affichage précisant l’emplacement de HEAD et la branche qu’il référence :

HEAD -> master

Attention chéri·e, ça va trancher

Tu as probablement noté que j’indiquais plus haut que HEAD référence généralement une branche.

Disons qu’il s’agit du comportement pour les usages classiques. Restent certains usages à la marge qui nécessitent de ne pas référencer une branche, que ce soit pour se remettre à l’état d’une version antérieure sans risquer de faire régresser le projet (switch ou checkout), ou par le biais du comportement inhérent à certaines commandes (rebase, bisect, submodule…).

On se retrouve alors dans une situation dite de « tête détachée » (ou « HEAD détachée » dans le guide officiel, probablement pour le côté moins gore 🔪😱).

HEAD renseigne alors non plus une référence de branche mais directement un commit :

# Regardons l’état de HEAD quand elle est détachée
$ cat .git/HEAD
# Toujours une ligne, mais avec l’identifiant direct du commit courant
377758e1b6a31850f0307abb1ac5f039da53e17f

On discutera dans un prochain article de ce mécanisme et des moyens d’en sortir ou de s’en prémunir.

Tu veux aller plus loin et maîtriser pleinement les fondamentaux de Git ou être accompagné pour garantir la qualité de tes projets grâce à une bonne mise en place de Git ? On peut t’aider ou te former, il suffit de nous décrire ton besoin !