usar una tipos tener tag sirve qué proyecto podemos para nuestros nos mayor herramienta hacer existen etiquetas etiqueta cuando crear creamos control comando git internal

una - ¿Qué contiene el índice git EXACTAMENTE?



¿para qué nos sirve el sha-1 cuando creamos tags? (3)

Bit a bit de análisis

He decidido hacer algunas pruebas para comprender mejor el formato 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 objeto de árbol estándar, y su formato es binario y está documentado en: git/git/Documentation/technical/index-format.txt

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

Preparar

Cuando comenzamos un repositorio de prueba con:

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

El directorio .git ve así:

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

Y si obtenemos el contenido del único objeto:

git cat-file -p 78981922613b2afb6025042ff6bd878ac1994e85

Obtenemos a . Esto indica que:

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

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

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 formato: 2. El formato de índice ha evolucionado con el tiempo. Actualmente existe una versión hasta 4. El formato del índice no debería ser un problema cuando se colabora con diferentes computadoras en GitHub porque los repositorios simples no almacenan el índice: se genera en el momento de la clonación.

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

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

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

    Tenga en cuenta 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 archivo

      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 las configuraciones de usuario único.

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

  • al comienzo de la línea 30 : 00 00 00 02 : tamaño del archivo: 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 entrada. Tenga en cuenta 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: https://stackoverflow.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 : archivo 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 archivo para la suma de comprobación.

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

¿Qué contiene exactamente el índice de Git y qué comando 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 árbol de trabajo. Solo tengo curiosidad sobre en qué consiste un objeto de índice. Supongo que podría ser una lista de nombre de archivo / directorio, SHA-1 pares, un tipo de árbol virtual tal vez?

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


El índice de Git es un área de transición entre su directorio de trabajo y su repositorio. Puede usar el índice para crear un conjunto 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 directorio de trabajo.

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

git status

Cuando ejecuta el estado de git, puede ver qué archivos 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 this . Una búsqueda en Google arroja muchos enlaces, que deberían ser bastante autosuficientes.


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

El índice es un archivo binario (generalmente guardado en .git/index ) que contiene una lista ordenada de nombres de ruta, cada uno con permisos y SHA1 de un objeto 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 árbol de trabajo virtual al registrar una lista de rutas y sus nombres de objeto y sirve como área de preparación para escribir el siguiente objeto de árbol 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 archivos en el árbol de trabajo.

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

El archivo de índice Git tiene el siguiente formato

Todos los números binarios están en orden de bytes de red.
La versión 2 se describe aquí a menos 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 entradas de índice de 32 bits.
  • Una cantidad de entradas de índice ordenadas.
  • Extensiones :
    Las extensiones se identifican por la firma.
    Las extensiones opcionales se pueden ignorar si Git no las entiende.
    Git actualmente admite el árbol en caché 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 archivo de índice antes de esta suma de comprobación.

mljrg mljrg :

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 archivos rastreados (nombre de objeto, bits de modo y número de etapa en la salida).

Esa lista (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 referencia la sucursal a la que acaba de cambiar.