-
1. DĂ©marrage rapide
-
2. Les bases de Git
-
3. Les branches avec Git
-
4. Git sur le serveur
- 4.1 Protocoles
- 4.2 Installation de Git sur un serveur
- 4.3 Génération des clés publiques SSH
- 4.4 Mise en place du serveur
- 4.5 DĂ©mon (Daemon) Git
- 4.6 HTTP intelligent
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Git hébergé
- 4.10 Résumé
-
5. Git distribué
-
6. GitHub
-
7. Utilitaires Git
- 7.1 SĂ©lection des versions
- 7.2 Indexation interactive
- 7.3 Remisage et nettoyage
- 7.4 Signer votre travail
- 7.5 Recherche
- 7.6 RĂ©Ă©crire lâhistorique
- 7.7 Reset démystifié
- 7.8 Fusion avancée
- 7.9 Rerere
- 7.10 DĂ©boguer avec Git
- 7.11 Sous-modules
- 7.12 Empaquetage (bundling)
- 7.13 Replace
- 7.14 Stockage des identifiants
- 7.15 Résumé
-
8. Personnalisation de Git
- 8.1 Configuration de Git
- 8.2 Attributs Git
- 8.3 Crochets Git
- 8.4 Exemple de politique gérée par Git
- 8.5 Résumé
-
9. Git et les autres systĂšmes
- 9.1 Git comme client
- 9.2 Migration vers Git
- 9.3 Résumé
-
10. Les tripes de Git
- 10.1 Plomberie et porcelaine
- 10.2 Les objets de Git
- 10.3 Références Git
- 10.4 Fichiers groupés
- 10.5 La refspec
- 10.6 Les protocoles de transfert
- 10.7 Maintenance et récupération de données
- 10.8 Les variables dâenvironnement
- 10.9 Résumé
-
A1. Annexe A: Git dans dâautres environnements
- A1.1 Interfaces graphiques
- A1.2 Git dans Visual Studio
- A1.3 Git dans Visual Studio Code
- A1.4 Git dans IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git dans Sublime Text
- A1.6 Git dans Bash
- A1.7 Git dans Zsh
- A1.8 Git dans PowerShell
- A1.9 Résumé
-
A2. Annexe B: Embarquer Git dans vos applications
- A2.1 Git en ligne de commande
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Commandes Git
- A3.1 Installation et configuration
- A3.2 Obtention et création des projets
- A3.3 Capture dâinstantanĂ© basique
- A3.4 Création de branches et fusion
- A3.5 Partage et mise Ă jour de projets
- A3.6 Inspection et comparaison
- A3.7 DĂ©bogage
- A3.8 Patchs
- A3.9 Courriel
- A3.10 SystĂšmes externes
- A3.11 Administration
- A3.12 Commandes de plomberie
10.2 Les tripes de Git - Les objets de Git
Les objets de Git
Git est un systĂšme de fichier adressables par contenu. Super ! Mais quâest-ce que ça veut dire ? Ăa veut dire que le cĆur de Git est une simple base de paires clĂ©/valeur. Vous pouvez y insĂ©rer nâimporte quelle sorte de donnĂ©es et il vous retournera une clĂ© que vous pourrez utiliser Ă nâimporte quel moment pour rĂ©cupĂ©rer ces donnĂ©es.
Pour illustrer cela, vous pouvez utiliser la commande de plomberie hash-object
, qui prend des données, les stocke dans votre répertoire .git
, puis retourne la clé sous laquelle les données sont stockées.
Tout dâabord, crĂ©ez un nouveau dĂ©pĂŽt Git et vĂ©rifiez que rien ne se trouve dans le rĂ©pertoire objects
 :
$ git init test
Initialized empty Git repository in /tmp/test/.git/
$ cd test
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
$ find .git/objects -type f
Git a initialisé le répertoire objects
et y a créé les sous-répertoires pack
et info
, mais ils ne contiennent pas de fichier régulier.
Maintenant, stockez du texte dans votre base de données Git :
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4
Câest la forme la plus simple, git hash-object
prendrait le contenu que vous lui passez et retournerait simplement la clé unique qui serait utilisée pour le stocker dans la base de données Git.
Lâoption -w
spécifie à hash-object
de stocker lâobjet, sinon la commande rĂ©pondrait seulement quelle serait la clĂ©.
--stdin
spĂ©cifie Ă la commande de lire le contenu depuis lâentrĂ©e standard, sinon hash-object
sâattend Ă trouver un chemin vers un fichier.
La sortie de la commande est une empreinte de 40 caractĂšres. Câest lâempreinte SHA-1 â une somme de contrĂŽle du contenu du fichier que vous stockez plus un en-tĂȘte, que vous apprendrez sous peu. Voyez maintenant comment Git a stockĂ© vos donnĂ©es :
$ find .git/objects -type f
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
Vous pouvez voir un fichier dans le répertoire objects
.
Câest comme cela que Git stocke initialement du contenu â un fichier par contenu, nommĂ© dâaprĂšs la somme de contrĂŽle SHA-1 du contenu et de son en-tĂȘte.
Le sous-rĂ©pertoire est nommĂ© dâaprĂšs les 2 premiers caractĂšres de lâempreinte et le fichier dâaprĂšs les 38 caractĂšres restants.
Vous pouvez récupérer le contenu avec la commande cat-file
.
Cette commande est un peu le couteau suisse pour lâinspection des objets Git.
Lui passer lâoption -p
ordonne Ă la commande cat-file
de dĂ©terminer le type de contenu et de vous lâafficher joliment :
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content
Vous pouvez maintenant ajouter du contenu Ă Git et le rĂ©cupĂ©rer Ă nouveau. Vous pouvez faire de mĂȘme avec le contenu de fichiers. Par exemple, vous pouvez mettre en Ćuvre une gestion de version simple dâun fichier. Dâabord, crĂ©ez un nouveau fichier et enregistrez son contenu dans la base de donnĂ©es :
$ echo 'version 1' > test.txt
$ git hash-object -w test.txt
83baae61804e65cc73a7201a7252750c76066a30
Puis, modifiez le contenu du fichier et enregistrez-le à nouveau :
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
Votre base de données contient les 2 versions du fichier, ainsi que le premier contenu que vous avez stocké ici :
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
Vous pouvez maintenant restaurer le fichier à sa premiÚre version :
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
$ cat test.txt
version 1
ou à sa seconde version :
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
$ cat test.txt
version 2
Mais se rappeler de la clĂ© SHA-1 de chaque version de votre fichier nâest pas pratique.
En plus, vous ne stockez pas le nom du fichier dans votre systĂšme â seulement le contenu.
Ce type dâobjet est appelĂ© un blob (Binary Large OBject, soit en français : Gros Objet Binaire).
Git peut vous donner le type dâobjet de nâimporte quel objet Git, Ă©tant donnĂ© sa clĂ© SHA-1, avec cat-file -t
 :
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
blob
Les objets arbres
Le prochain type que nous allons Ă©tudier est lâarbre (tree) qui rĂ©sout le problĂšme de stockage du nom du fichier et vous permet dâenregistrer un groupe de fichiers ensemble. Git stocke du contenu de la mĂȘme maniĂšre, mais plus simplement, quâun systĂšme de fichier UNIX. Tout le contenu est stockĂ© comme des objets de type arbre ou blob : un arbre correspondant Ă un rĂ©pertoire UNIX et un blob correspond Ă peu prĂšs aux inodes ou au contenu dâun fichier. Un unique arbre contient une ou plusieurs entrĂ©es, chacune Ă©tant lâempreinte SHA-1 dâun blob ou dâun sous-arbre (sub-tree) avec ses droits dâaccĂšs (mode), son type et son nom de fichier associĂ©s. Lâarbre le plus rĂ©cent dâun projet pourrait ressembler, par exemple, Ă ceci :
$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
La syntaxe master^{tree}
signifie lâobjet arbre qui est pointĂ© par le dernier commit de la branche master
.
Remarquez que le sous-répertoire lib
nâest pas un blob, mais un pointeur vers un autre arbre :
$ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb
Note
|
En fonction du shell que vous utilisez, vous pouvez rencontrer des erreurs lors de lâutilisation de la syntaxe Dans CMD sous Windows, le caractĂšre Si vous utilisez ZSH, le caractĂšre |
Conceptuellement, les données que Git stocke ressemblent ceci :
Vous pouvez facilement créer votre propre arbre.
Git crĂ©e habituellement un arbre Ă partir de lâĂ©tat de la zone dâattente ou index et Ă©crit une sĂ©rie dâobjets arbre Ă partir de lĂ .
Donc, pour crĂ©er un objet arbre, vous devez dâabord mettre en place un index en mettant quelques fichiers en attente.
Pour créer un index contenant une entrée, la premiÚre version de votre fichier test.txt
par exemple, utilisons la commande de plomberie update-index
.
Vous pouvez utiliser cette commande pour ajouter artificiellement une version plus ancienne Ă une nouvelle zone dâattente.
Vous devez utiliser les options --add
car le fichier nâexiste pas encore dans votre zone dâattente (vous nâavez mĂȘme pas encore mis en place une zone dâattente) et --cacheinfo
car le fichier que vous ajoutez nâest pas dans votre rĂ©pertoire, mais dans la base de donnĂ©es.
Vous pouvez ensuite préciser le mode, SHA-1 et le nom de fichier :
$ git update-index --add --cacheinfo 100644 \
83baae61804e65cc73a7201a7252750c76066a30 test.txt
Dans ce cas, vous précisez le mode 100644
, qui signifie que câest un fichier normal.
Les alternatives sont 100755
, qui signifie que câest un exĂ©cutable, et 120000
, qui prĂ©cise que câest un lien symbolique.
Le concept de « mode » a Ă©tĂ© repris des mode UNIX, mais est beaucoup moins flexible : ces trois modes sont les seuls valides pour Git, pour les fichiers (blobs) dans Git (bien que dâautres modes soient utilisĂ©s pour les rĂ©pertoires et sous-modules).
Vous pouvez maintenant utiliser la commande write-tree
pour Ă©crire la zone dâattente dans un objet arbre.
Lâoption -w
est inutile (appeler write-tree
crĂ©e automatiquement un objet arbre Ă partir de lâĂ©tat de lâindex si cet arbre nâexiste pas) :
$ git write-tree
d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git cat-file -p d8329fc1cc938780ffdd9f94e0d364e0ea74f579
100644 blob 83baae61804e65cc73a7201a7252750c76066a30 test.txt
Vous pouvez Ă©galement vĂ©rifier que câest un objet arbre :
$ git cat-file -t d8329fc1cc938780ffdd9f94e0d364e0ea74f579
tree
Vous allez créer maintenant un nouvel arbre avec la seconde version de test.txt
et aussi un nouveau fichier :
$ echo 'new file' > new.txt
$ git update-index test.txt
$ git update-index --add new.txt
Votre zone dâattente contient maintenant la nouvelle version de test.txt
ainsi que le nouveau fichier new.txt
.
Enregistrez cet arbre (câest-Ă -dire enregistrez lâĂ©tat de la zone dâattente ou index dans un objet arbre) et voyez Ă quoi il ressemble :
$ git write-tree
0155eb4229851634a0f03eb265b69f5a2d56f341
$ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
Remarquez que cet arbre contient des entrĂ©es pour les deux fichiers et que lâempreinte SHA-1 de test.txt
est lâempreinte de la « version 2 » de tout Ă lâheure (1f7a7a
).
Pour le plaisir, ajoutez le premier arbre à celui-ci, en tant que sous-répertoire.
Vous pouvez rĂ©cupĂ©rer un arbre de votre zone dâattente en exĂ©cutant read-tree
.
Dans ce cas, vous pouvez rĂ©cupĂ©rer un arbre existant dans votre zone dâattente comme Ă©tant un sous-arbre en utilisant lâoption --prefix
de read-tree
 :
$ git read-tree --prefix=bak d8329fc1cc938780ffdd9f94e0d364e0ea74f579
$ git write-tree
3c4e9cd789d88d8d89c1073707c3585e41b0e614
$ git cat-file -p 3c4e9cd789d88d8d89c1073707c3585e41b0e614
040000 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 bak
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
Si vous crĂ©iez un rĂ©pertoire de travail Ă partir du nouvel arbre que vous venez dâenregistrer, vous auriez deux fichiers Ă la racine du rĂ©pertoire de travail, ainsi quâun sous-rĂ©pertoire appelĂ© bak
qui contiendrait la premiĂšre version du fichier test.txt
.
Vous pouvez vous représenter les données que Git utilise pour ces structures comme ceci :
Les objets commit
Vous avez trois arbres qui dĂ©finissent diffĂ©rents instantanĂ©s du projet que vous suivez, mais le problĂšme prĂ©cĂ©dent persiste : vous devez vous souvenir des valeurs des trois empreintes SHA-1 pour accĂ©der aux instantanĂ©s. Vous nâavez pas non plus dâinformation sur qui a enregistrĂ© les instantanĂ©s, quand et pourquoi. Ce sont les informations Ă©lĂ©mentaires quâun objet commit stocke pour vous.
Pour crĂ©er un objet commit, il suffit dâexĂ©cuter commit-tree
et de prĂ©ciser lâempreinte SHA-1 dâun seul arbre et quels objets commit, sâil y en a, le prĂ©cĂšdent directement.
Commencez avec le premier arbre que vous avez créé :
$ echo 'first commit' | git commit-tree d8329f
fdf4fc3344e67ab068f836878b6c4951e3b15f3d
Note
|
Vous obtiendrez une valeur de hashage diffĂ©rente Ă cause dâun moment de crĂ©ation et dâune information dâauteur diffĂ©rents. De plus, bien quâen principe tout objet commit peut ĂȘtre reproduit prĂ©cisĂ©ment en lui fournissant la mĂȘme donnĂ©e, les dĂ©tails historiques de la construction de ce livre signifient que les empreintes de commit affichĂ©es peuvent ne pas correspondre aux commits donnĂ©s. Remplacez les valeurs de hashage de commit et dâĂ©tiquette par vos propres valeurs de somme de contrĂŽle dans la suite de ce chapitre. |
Vous pouvez voir votre nouvel objet commit avec git cat-file
 :
$ git cat-file -p fdf4fc3
tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579
author Scott Chacon <schacon@gmail.com> 1243040974 -0700
committer Scott Chacon <schacon@gmail.com> 1243040974 -0700
first commit
Le format dâun objet commit est simple : il contient lâarbre racine de lâinstantanĂ© du projet Ă ce moment, les informations sur lâauteur et le validateur (qui utilisent vos variables de configuration user.name
et user.email
et un horodatage); une ligne vide et le message de validation.
Ensuite, vous enregistrez les deux autres objets commit, chacun référençant le commit dont il est issu :
$ echo 'second commit' | git commit-tree 0155eb -p fdf4fc3
cac0cab538b970a37ea1e769cbbde608743bc96d
$ echo 'third commit' | git commit-tree 3c4e9c -p cac0cab
1a410efbd13591db07496601ebc7a059dd55cfe9
Chacun des trois objets commit pointe sur un des trois arbres dâinstantanĂ© que vous avez crĂ©Ă©s.
Curieusement, vous disposez maintenant dâun historique Git complet que vous pouvez visualiser avec la commande git log
, si vous la lancez sur le SHA-1 du dernier commit :
$ git log --stat 1a410e
commit 1a410efbd13591db07496601ebc7a059dd55cfe9
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:15:24 2009 -0700
third commit
bak/test.txt | 1 +
1 file changed, 1 insertion(+)
commit cac0cab538b970a37ea1e769cbbde608743bc96d
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:14:29 2009 -0700
second commit
new.txt | 1 +
test.txt | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
commit fdf4fc3344e67ab068f836878b6c4951e3b15f3d
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:09:34 2009 -0700
first commit
test.txt | 1 +
1 file changed, 1 insertion(+)
Fantastique.
Vous venez dâeffectuer les opĂ©rations bas niveau pour construire un historique Git sans avoir utilisĂ© une seule des commandes de haut niveau.
Câest lâessence de ce que fait Git quand vous exĂ©cutez les commandes git add
et git commit
.
Il stocke les blobs correspondant aux fichiers modifiĂ©s, met Ă jour lâindex, Ă©crit les arbres et ajoute les objets commit qui rĂ©fĂ©rencent les arbres racines venant juste avant eux.
Ces trois objets principaux (le blob, lâarbre et le commit) sont initialement stockĂ©s dans des fichiers sĂ©parĂ©s du rĂ©pertoire .git/objects
.
Voici tous les objets contenus dans le rĂ©pertoire exemple, commentĂ©s dâaprĂšs leur contenu :
$ find .git/objects -type f
.git/objects/01/55eb4229851634a0f03eb265b69f5a2d56f341 # tree 2
.git/objects/1a/410efbd13591db07496601ebc7a059dd55cfe9 # commit 3
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a # test.txt v2
.git/objects/3c/4e9cd789d88d8d89c1073707c3585e41b0e614 # tree 3
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 # test.txt v1
.git/objects/ca/c0cab538b970a37ea1e769cbbde608743bc96d # commit 2
.git/objects/d6/70460b4b4aece5915caf5c68d12f560a9fe3e4 # 'test content'
.git/objects/d8/329fc1cc938780ffdd9f94e0d364e0ea74f579 # tree 1
.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 # new.txt
.git/objects/fd/f4fc3344e67ab068f836878b6c4951e3b15f3d # commit 1
Si vous suivez les pointeurs internes de ces objets, vous obtenez un graphe comme celui-ci :
Stockage des objets
Nous avons parlĂ© plus tĂŽt de lâen-tĂȘte prĂ©sent avec le contenu. Prenons un moment pour Ă©tudier la façon dont Git stocke les objets. On verra comment stocker interactivement un objet blob (ici, la chaĂźne "what is up, doc?") avec le langage Ruby.
Vous pouvez démarrer Ruby en mode interactif avec la commande irb
 :
$ irb
>> content = "what is up, doc?"
> "what is up, doc?"
Git construit un en-tĂȘte qui commence avec le type de lâobjet, ici un blob. Ensuite, il ajoute un espace suivi de taille du contenu et enfin un octet nul :
>> header = "blob #{content.length}\0"
> "blob 16\u0000"
Git concatĂšne lâen-tĂȘte avec le contenu original et calcule lâempreinte SHA-1 du nouveau contenu.
En Ruby, vous pouvez calculer lâempreinte SHA-1 dâune chaĂźne en incluant la bibliothĂšque « digest/SHA-1 » via la commande require
, puis en appelant Digest::SHA1.hexdigest()
sur la chaßne :
>> store = header + content
> "blob 16\u0000what is up, doc?"
>> require 'digest/sha1'
> true
>> sha1 = Digest::SHA1.hexdigest(store)
> "bd9dbf5aae1a3862dd1526723246b20206e5fc37"
Comparons cela avec la sortie de git hash-object
.
Ici nous utilisons echo -n
pour Ă©viter dâajouter un retour Ă la ligne dans lâentrĂ©e.
$ echo -n "what is up, doc?" | git hash-object --stdin
bd9dbf5aae1a3862dd1526723246b20206e5fc37
Git compresse le nouveau contenu avec zlib, ce que vous pouvez faire avec la bibliothĂšque zlib de Ruby.
Dâabord, vous devez inclure la bibliothĂšque et ensuite exĂ©cuter Zlib::Deflate.deflate()
sur le contenu :
>> require 'zlib'
> true
>> zlib_content = Zlib::Deflate.deflate(store)
> "x\x9CK\xCA\xC9OR04c(\xCFH,Q\xC8,V(-\xD0QH\xC9O\xB6\a\x00_\x1C\a\x9D"
Finalement, vous enregistrerez le contenu compressé dans un objet sur le disque.
Vous dĂ©terminerez le chemin de lâobjet que vous voulez enregistrer (les deux premiers caractĂšres de lâempreinte SHA-1 formeront le nom du sous-rĂ©pertoire et les 38 derniers formeront le nom du fichier dans ce rĂ©pertoire).
En Ruby, on peut utiliser la fonction FileUtils.mkdir_p()
pour crĂ©er un sous-rĂ©pertoire sâil nâexiste pas.
Ensuite, ouvrez le fichier avec File.open()
et enregistrez le contenu compressé en appelant la fonction write()
sur la référence du fichier :
>> path = '.git/objects/' + sha1[0,2] + '/' + sha1[2,38]
> ".git/objects/bd/9dbf5aae1a3862dd1526723246b20206e5fc37"
>> require 'fileutils'
> true
>> FileUtils.mkdir_p(File.dirname(path))
> ".git/objects/bd"
>> File.open(path, 'w') { |f| f.write zlib_content }
> 32
VĂ©rifions le contenu du fichier au moyen de git cat-file
 :
---
$ git cat-file -p bd9dbf5aae1a3862dd1526723246b20206e5fc37
what is up, doc?
---
Câest tout ! Vous venez juste de crĂ©er un objet blob valide.
Tout les objets Git sont stockĂ©s de la mĂȘme façon, mais avec des types diffĂ©rents : lâen-tĂȘte commencera par « commit » ou « tree » au lieu de la chaĂźne « blob ». De plus, alors que le contenu dâun blob peut ĂȘtre Ă peu prĂšs nâimporte quoi, le contenu dâun commit ou dâun arbre est formatĂ© de façon trĂšs prĂ©cise.