web-dev-qa-db-fra.com

Qu'est-ce que l'index git contient EXACTEMENT?

Que contient exactement l'index Git et quelle commande puis-je utiliser pour afficher le contenu de l'index?


Mise à jour

Merci pour toutes vos réponses. Je sais que l'index agit comme une zone intermédiaire et que ce qui est engagé est dans l'index plutôt que dans l'arborescence de travail. Je suis simplement curieux de savoir en quoi consiste un objet index. Je suppose que cela pourrait être une liste de nom de fichier/nom de répertoire, paires SHA-1, une sorte d'arborescence virtuelle peut-être?

Existe-t-il, dans la terminologie Git, une commande de plomberie que je peux utiliser pour répertorier le contenu de l'index?

165
mochidino

Le livre Git contient un article sur ce qu’un index comprend :

L'index est un fichier binaire (généralement conservé dans .git/index) Contenant une liste triée de noms de chemins d'accès, chacun avec des autorisations et le SHA1 d'un objet blob; git ls-files Peut vous montrer le contenu de l'index:

$ git ls-files --stage
100644 63c918c667fa005ff12ad89437f2fdc80926e21c 0   .gitignore
100644 5529b198e8d14decbe4ad99db3f7fb632de0439d 0   .mailmap

Le problème de Racy Git donne quelques détails supplémentaires sur cette structure:

L'index est l'une des structures de données les plus importantes de git.
Il représente un état d’arborescence de travail virtuel en enregistrant une liste de chemins et leurs noms d’objets et sert de zone de transfert pour écrire le prochain objet en arborescence à valider.
L’État est "virtuel" en ce sens qu’il ne doit pas nécessairement correspondre aux fichiers de l’arbre de travail, mais ne le fait souvent pas.


Pour en voir plus, cf. " git/git/documentation/technique/index-format.txt ":

Le fichier d'index Git a le format suivant

Tous les nombres binaires sont dans l’ordre des octets du réseau.
La version 2 est décrite ici, sauf indication contraire.

  • En-tête de 12 octets composé de:
    • Signature sur 4 octets :
      La signature est {'D', 'I', 'R', 'C'} (signifie "dircache ")
    • Numéro de version de 4 octets :
      Les versions actuellement prises en charge sont 2, 3 et 4.
    • Nombre 32 bits d'entrées d'index.
  • Un nombre de triés entrées d'index.
  • Extensions :
    Les extensions sont identifiées par une signature.
    Les extensions facultatives peuvent être ignorées si Git ne les comprend pas.
    Git prend actuellement en charge l’arborescence en mémoire cache et résout les extensions annulées.
    • Signature d'extension de 4 octets. Si le premier octet est 'A'..'Z', l'extension est facultative et peut être ignorée.
    • Taille de 32 bits de l'extension
    • Données d'extension
  • SHA-1 160 bits sur le contenu du fichier d’index avant cette somme de contrôle.

mljrgcommentaires :

Si l'index est l'endroit où le prochain commit est préparé, pourquoi "git ls-files -s" Ne renvoie rien après le commit?

Parce que , l'index représente ce qui est suivi , et juste après un commit, ce qui est suivi est identique au dernier commit (git diff --cached ne renvoie rien).

Donc git ls-files -s Liste tous les fichiers suivis (nom d'objet, bits de mode et numéro d'étape dans la sortie).

Cette liste (d'éléments suivis) est initialisée avec le contenu d'une validation.
Lorsque vous changez de branche, le contenu de l'index est réinitialisé sur le commit référencé par la branche que vous venez de basculer.


Git 2.20 (T4 2018) ajoute un tableau de décalage d'entrée d'index (IEOT) :

Voir commit 77ff112 , commit 3255089 , commit abb4bb8 , commit c780b9c , commit 3b1d9e , commit 371ed0d (10 octobre 2018) par Ben Peart (benpeart) .
Voir commit 252d079 (26 sept. 2018) par Nguyễn Thái Ngọc Duy (pclouds) .
(Fusionnée par Junio ​​C Hamano - gitster - dans commit e27bfaa , 19 octobre 2018)

ieot: ajouter une extension IEOT (Index Entry Offset Table)

Ce correctif permet d’adresser le coût du processeur lié au chargement de l’index en ajoutant des données supplémentaires à l’index, ce qui nous permettra de gérer efficacement le chargement et la conversion d’entrées de cache.

Pour ce faire, il ajoute une extension d’index (facultative) qui est une table de décalages de blocs d’entrées de cache dans le fichier d’index.

Pour que cela fonctionne pour les index V4, lors de l'écriture des entrées de cache, il "réinitialise" périodiquement le préfixe de compression en codant l'entrée actuelle comme si le nom du chemin de l'entrée précédente était complètement différent et enregistrait le décalage de cette entrée dans l'IEOT. .
Fondamentalement, avec les index V4, il génère des décalages en blocs d’entrées compressées par préfixe.

Avec le nouveau paramètre de configuration index.threads , le chargement de l'index est maintenant plus rapide.


En conséquence ( avec IEOT ), commit 7bd9631 nettoie la fonction read-cache.c load_cache_entries_threaded() pour Git 2.23 (Q3 2019).

Voir commit 8373037 , commit d713e88 , commit d92349d , commit 113c29a , commit c95fc72 , commit 7a2a721 , commit c016579 , commit be27fb7 , commit 13a1781 , commit 7bd9631 , commit 3c1dce8 , commit cf7a901 , commit d64db5b , commit 76a7bc (09 mai 2019) par Jeff King (peff) .
(Fusionne par Junio ​​C Hamano - gitster - dans commit c0e78f7 , 13 juin 2019)

read-cache: supprime le paramètre inutilisé de la charge threadée

La fonction load_cache_entries_threaded() prend un paramètre src_offset Qu'elle n'utilise pas. Cela existe depuis sa création dans 77ff112 (read-cache: Charge les entrées de cache sur les threads de travail, 2018-10-10, Git v2.20.0-rc0).

En fouillant sur la liste de diffusion, ce paramètre faisait partie d'un itération précédente de la série , mais est devenu inutile lorsque le code est passé à l'aide de l'extension IEOT.

147
VonC

Analyse bit par bit

J'ai décidé de faire quelques essais pour mieux comprendre le format et approfondir la recherche sur certains domaines.

Les résultats ci-dessous sont les mêmes pour les versions de Git 1.8.5.2 Et 2.3.

J'ai marqué des points que je ne suis pas sûr/n'ai pas trouvé avec TODO: n'hésitez pas à compléter ces points.

Comme d'autres l'ont mentionné, l'index est stocké sous .git/index, Non pas comme un objet d'arborescence standard, et son format est binaire et documenté à l'adresse: https://github.com/git/git/blob/ master/Documentation/technique/index-format.txt

Les principales structures qui définissent l'index sont à cache.h , car l'index est un cache pour la création de commits.

Installer

Lorsque nous démarrons un référentiel de test avec:

git init
echo a > b
git add b
tree --charset=ascii

Le répertoire .git Ressemble à ceci:

.git/objects/
|-- 78
|   `-- 981922613b2afb6025042ff6bd878ac1994e85
|-- info
`-- pack

Et si nous obtenons le contenu du seul objet:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Nous obtenons a. Cela indique que:

  • le index pointe vers le contenu du fichier, puisque git add b a créé un objet blob
  • il stocke les métadonnées dans le fichier d'index, pas dans un objet tree, car il n'y avait qu'un seul objet: le blob (sur les objets Git normaux, les métadonnées de blob sont stockées sur l'arbre)

analyse HD

Maintenant regardons l'index lui-même:

hd .git/index

Donne:

00000000  44 49 52 43 00 00 00 02  00 00 00 01 54 09 76 e6  |DIRC.... ....T.v.|
00000010  1d 81 6f c6 54 09 76 e6  1d 81 6f c6 00 00 08 05  |..o.T.v. ..o.....|
00000020  00 e4 2e 76 00 00 81 a4  00 00 03 e8 00 00 03 e8  |...v.... ........|
00000030  00 00 00 02 78 98 19 22  61 3b 2a fb 60 25 04 2f  |....x.." a;*.`%./|
00000040  f6 bd 87 8a c1 99 4e 85  00 01 62 00 ee 33 c0 3a  |......N. ..b..3.:|
00000050  be 41 4b 1f d7 1d 33 a9  da d4 93 9a 09 ab 49 94  |.AK...3. ......I.|
00000060

Ensuite nous conclurons:

  | 0           | 4            | 8           | C              |
  |-------------|--------------|-------------|----------------|
0 | DIRC        | Version      | File count  | ctime       ...| 0
  | ...         | mtime                      | device         |
2 | inode       | mode         | UID         | GID            | 2
  | File size   | Entry SHA-1                              ...|
4 | ...                        | Flags       | Index SHA-1 ...| 4
  | ...                                                       |

Vient d'abord l'en-tête, défini à: struct cache_header :

  • 44 49 52 43: DIRC. TODO: pourquoi est-ce nécessaire?

  • 00 00 00 02: Version du format: 2. Le format de l'index a évolué avec le temps. Il existe actuellement une version allant jusqu'à 4. Le format de l'index ne devrait pas être un problème lors de la collaboration entre différents ordinateurs sur GitHub car les référentiels nus ne stockent pas l'index: il est généré au moment du clonage.

  • 00 00 00 01: Nombre de fichiers de l'index: un seul, b.

Next commence une liste d'entrées d'index, définies par struct cache_entry Nous n'en avons qu'une. Il contient:

  • un tas de métadonnées de fichier: 8 octets ctime, 8 octets mtime, puis 4 octets: périphérique, inode, mode, UID et GID.

    Notez comment:

    • ctime et mtime sont identiques (54 09 76 e6 1d 81 6f c6) comme prévu car nous n'avons pas modifié le fichier.

      Les premiers octets sont des secondes depuis Epoch en hex:

      date --date="@$(printf "%x" "540976e6")"
      

      Donne:

      Fri Sep  5 10:40:06 CEST 2014
      

      C'est à ce moment que j'ai fait cet exemple.

      Les 4 derniers octets sont en nanosecondes.

    • L'UID et le GID sont 00 00 03 e8, 1000 en hex: une valeur commune pour les configurations à utilisateur unique.

    Toutes ces métadonnées, dont la plupart ne sont pas présentes dans les objets de l'arborescence, permettent à Git de vérifier si un fichier a été modifié rapidement sans comparer le contenu complet.

  • au début de la ligne 30: 00 00 00 02: taille du fichier: 2 octets (a et \n à partir de echo)

  • 78 98 19 22 ... c1 99 4e 85: 20 octets SHA-1 sur le contenu précédent de l'entrée. Notez que selon mes expériences avec le drapeau supposant valide , les drapeaux qui le suivent ne sont pas pris en compte dans ce SHA-1.

  • Drapeaux 2 octets: 00 01

    • 1 bit: supposer un drapeau valide. Mes enquêtes indiquent que cet indicateur mal nommé est où git update-index --assume-unchanged Stocke son état: https://stackoverflow.com/a/28657085/895245

    • Drapeau étendu 1 bit. Détermine si les indicateurs étendus sont présents ou non. Doit être 0 Sur la version 2 qui n'a pas d'indicateur étendu.

    • Indicateur d'étape 2 bits utilisé lors de la fusion. Les étapes sont documentées dans man git-merge:

      • 0: Fichier normal, pas dans un conflit de fusion
      • 1: Base
      • 2: Le nôtre
      • 3: Leur

      Lors d'un conflit de fusion, toutes les étapes de 1 à 3 sont stockées dans l'index pour permettre des opérations telles que git checkout --ours.

      Si vous git add, Une étape 0 est ajoutée à l'index du chemin, et Git saura que le conflit a été marqué comme résolu. TODO: vérifie ça.

    • Longueur de 12 bits du chemin qui suivra: 0 01: 1 octet seulement car le chemin était b

  • Drapeaux étendus sur 2 octets. N'a de sens que si "l'indicateur étendu" a été défini sur les indicateurs de base. FAIRE.

  • 62 (ASCII b): chemin de longueur variable. Longueur déterminée dans les drapeaux précédents, ici juste un octet, b.

Vient ensuite un 00: 1-8 octets de remplissage zéro de sorte que le chemin soit terminé par un octet nul et que l'index se termine par un multiple de 8 octets. Cela se produit uniquement avant la version 4 de l'index.

Aucune extension n'a été utilisée. Git le sait parce qu'il n'y aurait pas assez d'espace dans le fichier pour la somme de contrôle.

Enfin, il y a une somme de contrôle de 20 octets ee 33 c0 3a .. 09 ab 49 94 Sur le contenu de l'index.

L'index Git est une zone de transfert entre votre répertoire de travail et votre référentiel. Vous pouvez utiliser l'index pour créer un ensemble de modifications que vous souhaitez valider ensemble. Lorsque vous créez un commit, ce qui est commis est ce qui se trouve actuellement dans cet index, pas ce qui se trouve dans votre répertoire de travail.

Pour voir ce qui se trouve dans l'index, lancez la commande:

git status

Lorsque vous exécutez git status, vous pouvez voir quels fichiers sont en cours de traitement (actuellement dans votre index), qui sont modifiés mais pas encore, et qui sont complètement non suivis.

Vous pouvez lire this . Une recherche sur Google génère de nombreux liens, qui devraient être assez autonomes.

12
user225312

Voici ce dont vous aviez exactement besoin, utilisez cette commande.

$ binwalk index

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
1717          0x6B5           Unix path: /company/user/user/delete.php
1813          0x715           Unix path: /company/user/user/get.php
1909          0x775           Unix path: /company/user/user/post.php
2005          0x7D5           Unix path: /company/user/user/put.php
3373          0xD2D           Unix path: /urban-airship/channel/channel/post.php
3789          0xECD           Unix path: /urban-airship/named-user/named-user/post.php
3901          0xF3D           Unix path: /user/categories/categories/delete.php
4005          0xFA5           Unix path: /user/categories/categories/get.php
4109          0x100D          Unix path: /user/categories/categories/put.php
4309          0x10D5          Unix path: /user/favorites/favorites/delete.php
1
l h