-
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.3 Les tripes de Git - Références Git
Références Git
On peut exécuter quelque chose comme git log 1a410e
pour visualiser tout l’historique, mais il faut se souvenir que 1a410e
est le dernier commit afin de parcourir l’historique et trouver tous ces objets.
Vous avez besoin d’un fichier dans lequel vous pouvez stocker l’empreinte SHA-1 sous un nom simple afin d’utiliser ce pointeur plutôt que l’empreinte SHA-1 elle-même.
Git appelle ces pointeurs des « références », ou « refs ».
On trouve les fichiers contenant des empreintes SHA-1 dans le répertoire git/refs
.
Dans le projet actuel, ce répertoire ne contient aucun fichier, mais possède une structure simple :
$ find .git/refs
.git/refs
.git/refs/heads
.git/refs/tags
$ find .git/refs -type f
Pour créer une nouvelle référence servant à se souvenir du dernier commit, vous pouvez simplement faire ceci :
$ echo "1a410efbd13591db07496601ebc7a059dd55cfe9" > .git/refs/heads/master
Vous pouvez maintenant utiliser la référence principale que vous venez de créer à la place de l’empreinte SHA-1 dans vos commandes Git :
$ git log --pretty=oneline master
1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
cac0cab538b970a37ea1e769cbbde608743bc96d second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
Il n’est pas conseillé d’éditer directement les fichiers des références.
Git propose une manière sûre de mettre à jour une référence, c’est la commande update-ref
:
$ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9
C’est simplement ce qu’est une branche dans Git : un simple pointeur ou référence sur le dernier état d’une suite de travaux. Pour créer une branche à partir du deuxième commit, vous pouvez faire ceci :
$ git update-ref refs/heads/test cac0ca
Cette branche contiendra seulement le travail effectué jusqu’à ce commit :
$ git log --pretty=oneline test
cac0cab538b970a37ea1e769cbbde608743bc96d second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
La base de donnée Git ressemble maintenant à quelque chose comme ceci :
![Le répertoire d’objets de Git avec les références de branches incluses.](png/data-model-4.png)
Quand vous exécutez une commande comme git branch (nomdebranche)
, Git exécute simplement la commande update-ref
pour ajouter l’empreinte SHA-1 du dernier commit de la branche sur laquelle vous êtes quelle que soit la nouvelle référence que vous voulez créer.
La branche HEAD
On peut se poser la question : « Comment Git peut avoir connaissance de l’empreinte SHA-1 du dernier commit quand on exécute git branch (branchname)
? »
La réponse est dans le fichier HEAD (qui veut dire tête en français, soit, ici, l’état courant).
Habituellement, le fichier HEAD est une référence symbolique à la branche courante. Par référence symbolique, j’entends que contrairement à une référence normale, elle ne contient pas une empreinte SHA-1, mais plutôt un pointeur vers une autre référence.
Cependant dans certains cas rares, le fichier HEAD peut contenir l’empreinte SHA-1 d’un objet git. Cela arrive quand vous extrayez une étiquette, un commit ou une branche distante, ce qui bascule le dépôt en état "HEAD détachée"
Si vous regardez ce fichier, vous devriez voir quelque chose comme ceci :
$ cat .git/HEAD
ref: refs/heads/master
Si vous exécutez git checkout test
, Git met à jour ce fichier, qui ressemblera à ceci :
$ cat .git/HEAD
ref: refs/heads/test
Quand vous exécutez git commit
, il crée l’objet commit en spécifiant le parent de cet objet commit quelle que soit l’empreinte SHA-1 pointée par la référence de HEAD.
On peut éditer manuellement ce fichier, mais encore une fois, il existe une commande plus sûre pour le faire : symbolic-ref
.
Vous pouvez lire le contenu de votre fichier HEAD avec cette commande :
$ git symbolic-ref HEAD
refs/heads/master
Vous pouvez aussi définir la valeur de HEAD :
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
ref: refs/heads/test
Vous ne pouvez pas définir une référence symbolique à une valeur non contenu dans refs :
$ git symbolic-ref HEAD test
fatal: Refusing to point HEAD outside of refs/
Étiquettes
Nous venons de parcourir les trois types d’objets utilisés par Git, mais il en existe un quatrième. L’objet étiquette (tag en anglais) ressemble beaucoup à un objet commit. Il contient un étiqueteur, une date, un message et un pointeur. La principale différence est que l’étiquette pointe en général vers un commit plutôt qu’un arbre. C’est comme une référence à une branche, mais elle ne bouge jamais : elle pointe toujours vers le même commit, lui donnant un nom plus sympathique.
Comme présenté dans Les bases de Git, il existe deux types d’étiquettes : annotée et légère. Vous pouvez créer une étiquette légère comme ceci :
$ git update-ref refs/tags/v1.0 cac0cab538b970a37ea1e769cbbde608743bc96d
C’est tout ce qu’est une étiquette légère : une référence qui n’est jamais modifiée.
Une étiquette annotée est plus complexe.
Quand on crée une étiquette annotée, Git crée un objet étiquette, puis enregistre une référence qui pointe vers lui plutôt que directement vers le commit.
Vous pouvez voir ceci en créant une étiquette annotée (-a
spécifie que c’est une étiquette annotée) :
$ git tag -a v1.1 1a410efbd13591db07496601ebc7a059dd55cfe9 -m 'test tag'
Voici l’empreinte SHA-1 de l’objet créé :
$ cat .git/refs/tags/v1.1
9585191f37f7b0fb9444f35a9bf50de191beadc2
Maintenant, exécutez la commande cat-file
sur cette empreinte SHA-1 :
$ git cat-file -p 9585191f37f7b0fb9444f35a9bf50de191beadc2
object 1a410efbd13591db07496601ebc7a059dd55cfe9
type commit
tag v1.1
tagger Scott Chacon <schacon@gmail.com> Sat May 23 16:48:58 2009 -0700
test tag
Remarquez que le contenu de l’objet pointe vers l’empreinte SHA-1 du commit que vous avez étiqueté. Remarquez qu’il n’est pas nécessaire qu’il pointe vers un commit. On peut étiqueter n’importe quel objet. Par exemple, dans le code source de Git, le mainteneur a ajouté sa clé publique GPG dans un blob et a étiqueté ce blob. Vous pouvez voir la clé publique en exécutant ceci sur un clone du dépôt Git :
$ git cat-file blob junio-gpg-pub
Le noyau Linux contient aussi une étiquette ne pointant pas vers un commit : la première étiquette créée pointe vers l’arbre initial lors de l’importation du code source.
Références distantes
Le troisième type de références que l’on étudiera sont les références distantes (remotes).
Si l’on ajoute une référence distante et que l’on pousse des objets vers elle, Git stocke la valeur que vous avez poussée en dernier vers cette référence pour chaque branche dans le répertoire refs/remotes
.
Vous pouvez par exemple ajouter une référence distante nommée origin
et y pousser votre branche master
:
$ git remote add origin git@github.com:schacon/simplegit-progit.git
$ git push origin master
Counting objects: 11, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (7/7), 716 bytes, done.
Total 7 (delta 2), reused 4 (delta 1)
To git@github.com:schacon/simplegit-progit.git
a11bef0..ca82a6d master -> master
Ensuite, vous pouvez voir l’état de la branche master
dans la référence distante origin
la dernière fois que vous avez communiqué avec le serveur en regardant le fichier refs/remotes/origin/master
:
$ cat .git/refs/remotes/origin/master
ca82a6dff817ec66f44342007202690a93763949
Les références distantes diffèrent des branches (références refs/heads
) principalement parce qu’on ne peut y accéder qu’en lecture seule.
Vous pouvez exécuter git checkout
sur l’une d’entre elles, mais Git ne fera jamais pointer HEAD sur l’une d’elles, donc vous ne pourrez jamais en mettre une à jour en utilisant une commande commit
.
Git les gère comme des marque-pages du dernier état connu de vers quoi ces branches pointent sur le serveur.