¿Qué contiene el índice git EXACTAMENTE?

¿Qué contiene exactamente el índice de Git y qué command puedo usar para ver el contenido del índice?


Actualizar

Gracias por todas sus respuestas. Sé que el índice actúa como un área de transición, y lo que está comprometido está en el índice en lugar del tree de trabajo. Solo tengo curiosidad sobre en qué consiste un object de índice. Supongo que podría ser una list de nombre de file / directory, SHA-1 pares, un tipo de tree virtual tal vez?

¿Existe, en la terminología de Git, algún command de plomería que pueda usar para enumerar los contenidos del índice?

El libro de Git contiene un artículo sobre lo que incluye un índice :

El índice es un file binary (generalmente guardado en .git/index ) que contiene una list orderada de nombres de ruta, cada uno con permissions y SHA1 de un object blob; git ls-files puede mostrarle el contenido del índice:

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

El problema de Racy git brinda más detalles sobre esa estructura:

El índice es una de las estructuras de datos más importantes en git.
Representa un estado de tree de trabajo virtual al registrar una list de routes y sus nombres de object y sirve como área de preparación para escribir el siguiente object de tree que se va a comprometer.
El estado es "virtual" en el sentido de que no necesariamente tiene que coincidir, y a menudo no coincide, con los files en el tree de trabajo.


Para ver más, cf. " git / git / Documentation / technical / index-format.txt ":

El file de índice Git tiene el siguiente formatting

Todos los numbers binarys están en order de bytes de networking.
La versión 2 se describe aquí a less que se indique lo contrario.

  • Un encabezado de 12 bytes que consiste en:
    • Firma de 4 bytes:
      La firma es {' D ', ' I ', ' R ', ' C '} (significa " dircache ")
    • Número de versión de 4 bytes:
      Las versiones admitidas actuales son 2, 3 y 4.
    • Número de inputs de índice de 32 bits.
  • Una cantidad de inputs de índice orderadas.
  • Extensiones :
    Las extensiones se identifican por la firma.
    Las extensiones opcionales se pueden ignorar si Git no las entiende.
    Git actualmente admite el tree en caching y resuelve extensiones de deshacer.
    • Firma de extensión de 4 bytes. Si el primer byte es ' A ' .. ' Z ', la extensión es opcional y se puede ignorar.
    • Tamaño de 32 bits de la extensión
    • Datos de extensión
  • SHA-1 de 160 bits sobre el contenido del file de índice antes de esta sum de comprobación.

mljrg comentarios :

Si el índice es el lugar donde está preparado el siguiente compromiso, ¿por qué " git ls-files -s " no devuelve nada después de la confirmación?

Como el índice representa lo que se está rastreando , y justo después de una confirmación, lo que se rastrea es idéntico al último compromiso ( git diff --cached no git diff --cached nada).

Entonces git ls-files -s enumera todos los files rastreados (nombre de object, bits de modo y número de etapa en la salida).

Esa list (del elemento rastreado) se inicializa con el contenido de una confirmación.
Cuando cambia de bifurcación, el contenido del índice se restablece a la confirmación a la que hace reference la sucursal a la que acaba de cambiar.

Bit a bit de análisis

He decidido hacer algunas testings para comprender mejor el formatting e investigar algunos de los campos con más detalle.

Los resultados siguientes son los mismos para las versiones 1.8.5.2 y 2.3 Git.

He marcado puntos que no estoy seguro / no he encontrado con TODO : siéntase libre de complementar esos puntos.

Como otros mencionaron, el índice se almacena en .git/index , no como un object de tree estándar, y su formatting es binary y está documentado en: https://github.com/git/git/blob/master/Documentation/technical/ index-format.txt

Las principales estructuras que definen el índice están en cache.h , porque el índice es un caching para crear commits.

Preparar

Cuando comenzamos un repository de testing con:

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

El directory .git ve así:

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

Y si obtenemos el contenido del único object:

 git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85 

Obtenemos a . Esto indica que:

  • el index apunta al contenido del file, ya que git add b creó un object blob
  • almacena los metadatos en el file de índice, no en un object de tree, ya que solo había un único object: el blob (en los objects normales de Git, los metadatos de blobs se almacenan en el tree)

análisis de hd

Ahora veamos el índice en sí mismo:

 hd .git/index 

Da:

 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 

A continuación, concluiremos:

  | 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 | ... | 

Primero viene el encabezado, definido en: struct cache_header :

  • 44 49 52 43 : DIRC . TODO: ¿por qué es esto necesario?

  • 00 00 00 02 : versión de formatting: 2. El formatting de índice ha evolucionado con el time. Actualmente existe una versión hasta 4. El formatting del índice no debería ser un problema cuando se queuebora con diferentes computadoras en GitHub porque los repositorys simples no almacenan el índice: se genera en el momento de la clonación.

  • 00 00 00 01 : recuento de files en el índice: solo uno, b .

A continuación comienza una list de inputs de índice, definida por struct cache_entry. Aquí tenemos solo una. Contiene:

  • un montón de metadatos de files: 8 bytes de time, 8 bytes de mtime , luego 4 bytes: dispositivo, inode, modo, UID y GID.

    Tenga en count cómo:

    • ctime y mtime son los mismos ( 54 09 76 e6 1d 81 6f c6 ) como se esperaba, ya que no hemos modificado el file

      Los primeros bytes son segundos desde EPOCH en hexadecimal:

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

      Da:

       Fri Sep 5 10:40:06 CEST 2014 

      Que es cuando hice este ejemplo.

      Los segundos 4 bytes son nanosegundos.

    • UID y GID son 00 00 03 e8 , 1000 en hex: un valor común para configuraciones de usuario único.

    Todos estos metadatos, la mayoría de los cuales no están presentes en los objects de tree, le permiten a Git verificar si un file ha cambiado rápidamente sin comparar todo el contenido.

  • al comienzo de la línea 30 : 00 00 00 02 : tamaño del file: 2 bytes ( a y \n del echo )

  • 78 98 19 22 ... c1 99 4e 85 : 20 byte SHA-1 sobre el contenido anterior de la input. Tenga en count que de acuerdo con mis experimentos con la bandera de asumir válido , las banderas que lo siguen no se consideran en este SHA-1.

  • Indicadores de 2 bytes: 00 01

    • 1 bit: asume una bandera válida. Mis investigaciones indican que esta bandera mal llamada es donde git update-index --assume-unchanged almacena su estado: http://sofes.miximages.com/a/28657085/895245

    • Bandera extendida de 1 bit. Determina si los indicadores extendidos están presentes o no. Debe ser 0 en la versión 2, que no tiene banderas extendidas.

    • Indicador de etapa de 2 bits utilizado durante la fusión. Las etapas están documentadas en man git-merge :

      • 0 : file regular, no en un conflicto de combinación
      • 1 : base
      • 2 : nuestro
      • 3 : el suyo

      Durante un conflicto de fusión, todas las etapas de 1-3 se almacenan en el índice para permitir operaciones como git checkout --ours .

      Si git add , entonces se agrega una etapa 0 al índice de la ruta, y Git sabrá que el conflicto se ha marcado como resuelto. TODO: mira esto.

    • 12 bits de longitud de la ruta que seguirá: 0 01 : 1 byte solo desde que la ruta fue b

  • Indicadores extendidos de 2 bytes. Solo es significativo si la "bandera extendida" se estableció en las banderas básicas. QUE HACER.

  • 62 (ASCII b ): ruta de longitud variable. Longitud determinada en los indicadores anteriores, aquí solo 1 byte, b .

Luego viene un 00 : 1-8 bytes de relleno cero para que la ruta sea terminada en nulo y el índice termine en un múltiplo de 8 bytes. Esto solo ocurre antes de la versión de índice 4.

No se usaron extensiones Git lo sabe porque no habría suficiente espacio en el file para la sum de comprobación.

Finalmente hay una sum de comprobación de 20 bytes ee 33 c0 3a .. 09 ab 49 94 sobre el contenido del índice.

El índice de Git es un área de transición entre su directory de trabajo y su repository. Puede usar el índice para crear un set de cambios que quiera comprometer juntos. Cuando crea un compromiso, lo que se compromete es lo que está actualmente en este índice, no lo que está en su directory de trabajo.

Para ver qué hay dentro del índice, ejecute el command:

 git status 

Cuando ejecuta el estado de git, puede ver qué files están organizados (actualmente en su índice), que están modificados pero que aún no están organizados y que están completamente sin seguimiento.

Puedes leer esto . Una búsqueda en Google arroja muchos enlaces, que deberían ser bastante autosuficientes.