Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Git comme on vous en a sans doute jamais parlé – Partie 1/2

Poster un commentaire

J’utilise Git sur divers projets depuis quelques temps déjà. Généralement tout se passe bien, j’ai repéré les commandes importantes, les autres… je m’en passe,  mais j’ai peut être tord!

Le problème avec Git c’est qu’il y a une courbe d’apprentissage un peu plus haute qu’avec d’autres repositories comme TFS. Il faut bosser plus pour se sentir à l’aise.

Git a par contre un avantage sur nombre de ses concurrents, c’est d’être nettement moins boîte noire. C’est très facile de retracer ce qui se passe, comment ça se passe… mais encore faut t’il savoir où chercher dans les fichiers.

Mon ressentit est qu’il s’agit là d’une étape qui aide énormément à se sentir à l’aise avec l’outil.

 

C’est se dont va traiter cet article et le suivant. Nous allons soulever le capot et regarder le moteur.

Notez tout de même qu’il ne s’agit pas d’un article pour s’initier à Git. Il sera nécessaire de l’avoir un petit peu pratiqué pour le lire.

Git et hachage

Git est un outil destiné à effectuer le suivi de contenus ainsi que la persistance de leurs évolutions. Pour y parvenir Git associe chaque artefact qui lui est confié à une clef de hachage représentative de son contenu. L’algorithme de hachage est SHA1.

Une clef de hachage est une chaîne alphanumérique extrêmement sensible au contenu. Faites le test suivant pour bien vous en convaincre sur le site http://www.sha1-online.com.

2016-03-12_21-41-18

Simplement remplacer une majuscule par une minuscule génère une clef entièrement différente.

Il est possible de savoir quelle clef est associée à un objet dans un repository en lançant une commande comme:

git hash-object test.txt

Qui affiche son hash:

2016-03-13_08-50-46

Modifions son contenu:

2016-03-13_08-51-52

La clef est bien différente.

 

Avant de passer à la suite, créez un répertoire GitDemo dans lequel nous ferons nos expériences et alimentez le de la façon suivante:

tree GitDemo /F

2016-03-13_08-46-59

Deux fichiers dans GitDemo, un répertoire Data avec un autre fichier. Les fichiers sont vides à l »exception de test.txt. C’est cela qui constituera notre très modeste projet.

La base de données Git

Pour avoir quelque chose à tracer et à suivre il faut bien l’enregistrer quelque part. Ce quelque part est bien entendu un répertoire. Vous savez très bien que vous pouvez y faire ce que vous souhaitez, cela n’affectera pas pour autant Git. Un répertoire n’est pas suffisant, il faut le configurer pour devenir un repository Git, c’est à dire un répertoire dont Git surveille tout ce qui s’y passe:

git init

2016-03-12_21-59-49

Le message nous avertit qu’un repository Git a bien été initialisé dans un mystérieux fichier .git dont voici le contenu:

2016-03-12_22-50-19

Un repository Git c’est cela, un répertoire .git. Il suffit de le supprimer pour le perdre.

 

Le répertoire Objects est la base de données de Git qui va être le sujet de ce chapitre. Objects contient tous les artefacts suivis par Git: fichiers, répertoires, commit et tags annotés. Pour l’instant il est vide.

git status

2016-03-13_08-58-16

On nous confirme bien que les fichiers du projet ne sont pas suivis par Git bien que présents.

On va les insérer dans l’index Git (staging area) pour que Git puisse en assurer le suivi:

git add .

git status

2016-03-13_09-22-04

Notre projet a bien été poussé dans l’index et si on regarde la base de données:

tree .git/Objects /F

2016-03-13_09-02-39

 

Deux nouveaux répertoires sont apparus. La règle est simple:

  1. le nom du répertoire est composé des deux premiers caractères du hash (9e)
  2. le nom du contenu est composé du reste du hash (81b9c1f9f6be1f8224d5416f10b6507c9499c2)

Ce qui est facile à confirmer:

2016-03-13_09-24-01

Mais où est passé Data/donnees.txt qui apparaît pourtant dans le statut?

 

Le truc à bien comprendre est que le hash se réfère à un contenu, pas un nom de fichier. Il se trouve que donnees.txt et readme.txt sont vides tous les deux, ils aurons donc le même hash. Puisque deux fichiers sont identiques du point de vu de leur contenu, ils sont identiques du point de vue de Git.

 

Il est possible d’en examiner les contenus avec une commande que nous allons beaucoup utiliser, git cat-file:

git cat-file  e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 -p

git cat-file 9e81b9c1f9f6be1f8224d5416f10b6507c9499c2 -p

 

2016-03-13_09-32-27

 

Git assure bien sa fonction de suivit du contenu, il doit aussi assurer sa fonction de suivi des évolutions et du versionnage. Versionnons donc en lançant un commit:

git commit -m « Premier Commit »

git status

2016-03-13_09-39-51

Note: on peut utiliser une version abrégée:

git cat-file  e69d -p

Dans notre cas les 4 premiers digits suffisent pour identifier le contenu, Git saura le retrouver.

 

Revenons vers Objects:

2016-03-13_09-41-44

Il y a du monde en plus.

Il est temps de s’intéresser à la nature des artefacts de la base de données, ce que l’on peut obtenir avec le commutateur -t de cat-file:

git cat-file  e69d -t

2016-03-13_09-43-43

Ce contenu est un blob. C’est le nom des artefacts de contenu gérés par Git. On aboutit facilement à:

e69d => blob

b649 => commit

ab36 => tree

9e81 => blob

2727 => tree

 

Jusqu’à présent on n’avait que des blobs dans le repository, maintenant on a des objets de persistance comme commit et tree. C’est quoi?

 

Examinons le contenu d’un commit:

2016-03-13_09-49-38

 

C’est très simple. La première ligne est intéressante car elle nous indique le nom du tree (arbre). Un tree c’est l’équivalent d’un répertoire qui va contenir les fichiers qui ont été commités. Regardons son contenu:

git cat-file -p 2727

2016-03-13_09-52-37

Sans surprise ont retrouve les deux fichiers texte ainsi que le répertoire Data qui constitue le deuxième tree aperçu précédemment.

git cat-file -p ab36d

2016-03-13_09-55-10

On fait une dernière expérience en modifiant le contenu de readme.txt:

git commit -m « Deuxième Commit » -a

2016-03-13_10-10-55

Trois fichiers supplémentaires apparaissent:

2016-03-13_10-12-46

Vous devriez être en mesure de dire qu’il y a un blob, un commit et un tree. On récupère facilement l’identifiant du commit:

git log

2016-03-13_10-16-45

C’est d699.

git cat-file -p d699

2016-03-13_10-18-48

Cette fois nous avons l’indication du parent qui est le commit précédent. Poursuivons avec le tree:

git cat-file -p caf0ff

2016-03-13_10-20-51

 

Conclusions

Qu’avons nous appris?

Git effectue un suivit et organise la persistance des modifications grâce à une base de données située dans le répertoire Objects. Ce répertoire peut contenir 4 types d’objets:

  1. blob
  2. commit
  3. tree
  4. tag

Les contenus (blobs) ne sont pas dupliqués. Git procède à une optimisation basée sur le fait que les blobs sont des objets sauvegardés à part. Cela permet de sauvegarder une seule fois un contenu, même s’il correspond à des blogs dans des trees différents. Il suffit de faire un pointage vers le blob dans le tree.

 

Cette structure est très proche du système de fichiers organisés par Unix/Linux avec ses inodes. C’est exactement ça Git: une couche par dessus un système de fichiers. Je pense que tout de suite beaucoup de choses s’éclairent quand à l’architecture décentralisée de l’outil, la façon de gérer les branches, les liens…

 

Bibliographie

http://git-scm.com/book/tr/v2/Git-Internals-Git-Objects

http://git-scm.com/book/fr/v2/Les-tripes-de-Git-Plomberie-et-porcelaine

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Bibliographie

https://app.pluralsight.com/library/courses/how-git-works/exercise-files

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s