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?


Mettre à jour

Merci pour toutes vos réponses. Je sais que l’index agit comme une zone de transit et que ce qui est commis se trouve dans l’index plutôt que dans l’arborescence de travail. Je suis juste curieux de savoir en quoi consiste un object index. Je suppose que ce pourrait être une liste de noms de fichiers / répertoires, de paires SHA-1, une sorte d’arbre virtuel 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?

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

L’index est un fichier binary (généralement conservé dans .git/index ) contenant une liste sortingée de noms de chemins, chacun avec des permissions et le SHA1 d’un object 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 plus de détails 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 la liste des chemins d’access et leurs noms d’object et sert de zone de transfert pour écrire l’object d’arbre suivant à valider.
L’état est “virtuel” en ce sens qu’il ne doit pas nécessairement et souvent ne correspond pas aux fichiers de l’arborescence de travail.


Pour voir plus, cf. ” git / git / Documentation / technical / index-format.txt “:

Le fichier d’index Git a le format suivant

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

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

Commentaires de mljrg :

Si l’index est l’endroit où le prochain commit est préparé, pourquoi ” git ls-files -s ” ne renvoie-t-il rien après un commit?

Comme l’index représente ce qui est suivi et juste après une validation, ce qui est suivi est identique à la dernière validation ( git diff --cached ne renvoie rien).

Donc, git ls-files -s répertorie tous les fichiers suivis (nom de l’object, bits de mode et numéro d’étape dans la sortie).

Cette liste (d’élément suivi) est initialisée avec le contenu d’un commit.
Lorsque vous changez de twig, le contenu de l’index est réinitialisé sur la validation référencée par la twig vers laquelle vous venez de basculer.

Analyse bit par bit

J’ai décidé de faire quelques tests pour mieux comprendre le format et rechercher plus en détail certains domaines.

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

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 , pas comme un object d’arborescence standard, et son format est binary et documenté sur: https://github.com/git/git/blob/master/Documentation/technical/ 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 validations.

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 à:

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

Et si nous obtenons le contenu du seul object:

 git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85 

Nous avons a . Cela indique que:

  • l’ index pointe vers le contenu du fichier, car git add b créé un object blob
  • il stocke les métadonnées dans le fichier d’index, pas dans un object d’arbre, car il n’y avait qu’un seul object: le blob (sur les objects Git classiques, les métadonnées blob sont stockées dans l’arborescence)

parsing hd

Regardons maintenant 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.... ....Tv| 00000010 1d 81 6f c6 54 09 76 e6 1d 81 6f c6 00 00 08 05 |..oTv ..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 

Nous conclurons ensuite:

  | 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 de format: 2. Le format d’index a évolué avec le temps. Il existe actuellement une version allant jusqu’à 4. Le format de l’index ne devrait pas poser de problème lors de la collaboration entre différents ordinateurs sur GitHub, car les référentiels dénudés ne stockent pas l’index: ils sont générés au moment du clonage.

  • 00 00 00 01 : décompte des fichiers sur l’index: un seul, b .

Ensuite démarre une liste d’entrées d’index, définies par struct cache_entry. Ici nous n’en avons qu’une. Il contient:

  • un tas de métadonnées de fichiers: ctime 8 octets, ctime 8 octets, puis 4 octets: device, inode, mode, UID et GID.

    Notez comment:

    • ctime et ctime sont les mêmes ( 54 09 76 e6 1d 81 6f c6 ) que prévu puisque nous n’avons pas modifié le fichier

      Les premiers octets sont des secondes depuis EPOCH en hexadécimal:

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

      Donne:

       Fri Sep 5 10:40:06 CEST 2014 

      C’est quand j’ai fait cet exemple.

      Les 4 derniers octets sont des nanosecondes.

    • UID et GID sont 00 00 03 e8 , 1000 en hexadécimal: une valeur commune pour les configurations mono-utilisateur.

    Toutes ces métadonnées, dont la plupart ne sont pas présentes dans les objects arborescents, permettent à Git de vérifier si un fichier a changé rapidement sans comparer la totalité du contenu.

  • au début de la ligne 30 : 00 00 00 02 : taille du fichier: 2 octets ( a et \n de l’ 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 supposé valide , les indicateurs qui le suivent ne sont pas pris en compte dans ce SHA-1.

  • Drapeaux de 2 octets: 00 01

    • 1 bit: suppose un drapeau valide. Mes investigations indiquent que cet indicateur mal nommé est l’endroit où git update-index --assume-unchanged stocke son état: https://stackoverflow.com/a/28657085/895245

    • 1 bit drapeau étendu. Détermine si les indicateurs étendus sont présents ou non. Doit être 0 sur la version 2 qui n’a pas de drapeau étendu.

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

      • 0 : fichier régulier, pas dans un conflit de fusion
      • 1 : base
      • 2 : les nôtres
      • 3 : les leurs

      Pendant un conflit de fusion, toutes les étapes git checkout --ours entre 1 et 3 sont stockées dans l’index pour autoriser 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érifiez ceci.

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

  • Drapeaux étendus de 2 octets. Seulement significatif si le “drapeau étendu” a été défini sur les drapeaux de base. FAIRE.

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

Vient ensuite un 00 : 1-8 octets de remplissage nul pour que le chemin soit terminé par un caractère nul et que l’index se termine par un multiple de 8 octets. Cela se produit uniquement avant la version index 4.

Aucune extension n’a été utilisée. Git le sait car il n’y aurait plus assez d’espace dans le fichier pour la sum de contrôle.

Enfin, il existe un total de contrôle de 20 octets 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 une validation, ce qui est commis est ce qui est actuellement dans cet index, et non ce qui se trouve dans votre répertoire de travail.

Pour voir ce qu’il y a à l’intérieur de l’index, lancez la commande:

 git status 

Lorsque vous exécutez git status, vous pouvez voir quels fichiers sont mis en attente (actuellement dans votre index), qui sont modifiés mais pas encore mis en scène et qui ne sont pas suivis.

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