Voyons un peu ce qui se passe d'un point de vue plus technique, en analysant l'évolution des fichiers dans notre répertoire projet.

Je vais donc afficher dans le terminal à gauche les commandes et contenus de certains fichiers, et à droite nous verrons l’évolution de notre arborescence du sous-répertoire .git quand il sera créé.

Je commence par initialiser un dépôt vide. On voit alors à droite qu'un sous-répertoire .git/ a été créé et tout un tas de fichiers et répertoire déjà présents. Regardons ce qu'il contient en nous concentrons sur les aspects que nous avons déjà vu. Étant donné que le sous-ensemble qui correspond aux hooks ne nous intéresse pas pour ce cours, je vais le supprimer pour qu’il ne gêne pas l’affichage à droite. 

On retrouve en premier lieu un fichier HEAD : si on l'ouvre on voit qu'il ne contient qu'une ligne qui indique une référence refs: refs/heads/master, d'ailleurs on trouve le répertoire correspondant refs/heads/ mais sans le fichier master, et refs/tags.

Le répertoire objects/ fera office de base de données car c'est ici qu'on stockera les fichiers représentant l'historique, donc ceux issus de nos photos et de nos commits.

Nous créons ensuite un fichier et vérifions que rien n'a changé dans notre sous répertoire .git/. L'ajout de ce fichier à l‘index nous montre des évolutions au sein du répertoire.git/objects/.

Les répertoires sont découpés par les deux premiers caractères en raison d'une contrainte liée au système de fichiers NTFS qui limite le nombre de fichiers dans un répertoire. La clé du fichier est donc constituée des deux premiers caractères et des caractères restants.

Voyons ce que contient le fichier dans ce sous-répertoire. Si on l'ouvre avec un éditeur il est illisible car il a été compressé via zlib. On va donc analyser avec une commande de plomberie : git cat-file avec les options -t pour obtenir le type et -p pour lire le contenu. On voit donc que le fichier créé est un blob et que son contenu correspond bien à celui que nous avions créé.

On constate aussi la création d'un fichier index à la racine du répertoire .git et qui est donc notre fameux index. Son contenu est également est illisible sans Git. On va donc utiliser la commande de plomberie git ls-files pour nous montrer ce qu'il représente, et on voit qu'il contient une référence unique vers notre fichier.

On procède ensuite au commit et voyons qu'on a une nouvelle référence dans refs/heads/ et qui s'appelle master. Si on ouvre ce fichier on voit que ce fichier ne contient qu'une ligne, un identifiant SHA-1 de 40 caractères. D'ailleurs on retrouve cet identifiant dans notre sous répertoire .git/objects/.

Maintenant si on regarde ce fichier dans le détail avec git cat-file, on voit que c’est un bien un objet commit, et qu’il contient une référence vers un objet de type tree créé pour l’occasion. Et si on analyse ce fichier tree, on y trouve une référence vers le blob de notre fichier créé initialement.

Créons à présent une nouvelle branche dev et faisons pointer HEAD dessus pour la faire évoluer avec la commande git checkout -b dev

Si on vérifie dans le répertoire .git/refs on voit que le fichier .git/refs/heads/dev a bien été créé et qu'il contient bien la même référence que notre branche master actuelle (logique, elles pointe pour l'instant vers le même emplacement dans notre historique puisque HEAD pointe sur master). De même on peut vérifier que le fichier HEAD contient désormais une référence vers dev: ref: refs/heads/dev.

Si on modifie notre fichier et qu'on crée un nouveau commit sur cette branche dev on constate que le fichier .git/refs/heads/dev contient une nouvelle référence. Celle-ci est notre nouvel objet commit qui lui même pointe vers un nouveau tree racine qui à son tour référence le nouveau blob qui représente la photo de notre fichier modifié.

En résumé la création d'un commit modifiant notre fichier initial a créé un nouveau blob, un nouveau tree référençant ce blob, et un commit référençant ce tree.

Maintenant si je viens créer un nouveau fichier fichier-2, que je l’ajoute à l’index et que je créé un nouveau commit, si je regarde le contenu de ce nouveau commit avec la commande git show, on voit qu’il ajoute bien le fichier-2

Si on regarde le détail de cet objet commit dans notre base de données Git avec la commande git cat-file -p, on voit qu’il pointe bien vers un nouveau tree. On regarde alors le contenu de ce nouveau tree et on voit qu’il contient 2 références : une vers fichier, et une vers fichier-2

Regadez la référence vers fichier, il s’agit de la référence qu’on avait précédemment pour ce même fichier, c’est-à-dire que le commit qu’on vient de créer ici fait référence à la dernière version connue du fichier, on a donc pas recréer de blob en conséquence, on a réutilisé le dernier blob connu pour ce fichier.

Les concepts clés de Git

Git peut sembler mystérieux, mais comprendre ses concepts fonda­mentaux rend son utilisation lumineuse !