CaenHackYouAcademy
Git

Le modèle de données

Objets, empreintes, instantanés — ce que Git stocke réellement.

Presque tous les systèmes de version qui ont précédé Git enregistraient, pour chaque fichier, la liste des modifications successives. Git fait l'inverse : il enregistre l'état complet de l'arborescence à chaque commit.

Cela paraît coûteux. Ça ne l'est pas, parce qu'un fichier inchangé n'est pas recopié : le nouvel instantané réutilise l'objet existant. Le stockage suit le volume de ce qui change, pas le nombre de commits.

Trois types d'objets

Tout le contenu d'un dépôt tient dans trois structures, chacune identifiée par l'empreinte SHA-1 de son contenu.

ObjetContientAnalogie
bloble contenu d'un fichier, sans son nomle fichier
treedes noms, des permissions, et les empreintes associéesle répertoire
commitun tree racine, un ou plusieurs parents, auteur, date, messagel'instantané

Un fait qui surprend souvent : le nom du fichier n'est pas dans le blob. Il est dans le tree qui le référence. Deux fichiers de contenu identique, où qu'ils soient et quel que soit leur nom, partagent donc le même blob.

$ git cat-file -t 7f3k9q2      # quel type ?
commit
$ git cat-file -p 7f3k9q2      # son contenu
tree 8a1c3e9f4b2d7061a5c8e3f9b2d4a7c1e0f6b385
parent a91b4de2c7f0839e1d5a6b4c8e2f9017a3d5c6b8
author Karl <karl@exemple.fr> 1756598400 +0200
committer Karl <karl@exemple.fr> 1756598400 +0200

Corrige le calcul du budget d'erreurs

Un commit ne contient donc aucun fichier : il pointe vers un tree, qui pointe vers des blob et d'autres tree. C'est un graphe.

L'empreinte rend l'objet immuable

L'identifiant d'un objet est calculé à partir de son contenu. Changer une virgule au message d'un commit change son empreinte — donc ce n'est plus le même commit, mais un nouveau. L'ancien existe toujours, simplement plus personne ne le désigne.

C'est la clé pour comprendre amend, rebase et reset : aucun ne modifie un commit. Ils en créent d'autres et déplacent des pointeurs.

Comme le commit contient l'empreinte de son parent, modifier un commit ancien change tous ceux qui le suivent : leur parent n'a plus la même empreinte. C'est une chaîne vérifiable — la même idée qu'une chaîne de blocs, avec dix ans d'avance.

Un commit n'est pas perdu parce qu'il est invisible

Un commit qu'aucune branche ne désigne devient injoignable, pas supprimé. Il reste dans la base d'objets, retrouvable via git reflog, jusqu'au passage du ramasse-miettes — plusieurs semaines par défaut. C'est ce qui rend presque toutes les erreurs Git réversibles : voir Réparer.

La conséquence pratique

Puisque chaque commit porte l'arborescence complète, extraire n'importe quelle version est immédiat : il n'y a aucune différence à rejouer. C'est ce qui rend git checkout d'un commit vieux de trois ans aussi rapide que du dernier.

Et puisque l'identité vient du contenu, deux dépôts qui ont le même historique ont exactement les mêmes empreintes, sans s'être jamais parlé. C'est ce qui permet à Git d'être distribué : la comparaison de deux dépôts se fait sur des identifiants, sans autorité centrale.

VérificationQuestion 1 / 3

Réponse unique

Où est stocké le nom d'un fichier versionné ?

Indice · Qu'est-ce qui joue le rôle de répertoire dans le modèle ?

On this page