¿Por qué git diff-index HEAD cambia el resultado de los files tocados después del estado de git diff o git?

Si touch un file rastreado en un repository git, y ejecuto git diff-index HEAD , imprimirá salida con M indicando que el file ha sido modificado. Por ejemplo,

 $ touch foo $ git diff-index HEAD :100644 100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 0000000000000000000000000000000000000000 M foo 

No estoy seguro si esto tiene sentido o no, pero esa no es la pregunta. La pregunta es, ¿por qué la salida cambia (a no diff) si ejecuto git diff HEAD o git status ?

 $ touch foo $ git diff-index HEAD :100644 100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 0000000000000000000000000000000000000000 M foo $ git diff # no output $ git diff-index HEAD # no output 

Esperaría que el resultado, sea lo que sea, permanezca igual a través de commands que no se supone que cambien nada.

Primero veamos lo que significa el resultado:

 :100644 100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 0000000000000000000000000000000000000000 M foo 

El manual dice lo siguiente, de izquierda a derecha:

  1. un colon
  2. modo para "src"; 000000 si es creación o no.
  3. un espacio.
  4. modo para "dst"; 000000 si es eliminado o no.
  5. un espacio.
  6. sha1 para "src"; 0 {40} si es creación o no.
  7. un espacio.
  8. sha1 para "dst"; 0 {40} si la creación, sin fusionar o "mira tree de trabajo".
  9. un espacio.
  10. estado, seguido de un número de "puntuación" opcional.
  11. una pestaña o un NUL cuando se utiliza la opción -z.
  12. ruta para "src"
  13. una pestaña o NUL cuando se utiliza la opción -z; solo existe para C o R.
  14. path para "dst"; solo existe para C o R.
  15. una LF o una NUL cuando se utiliza la opción -z para finalizar el logging.

Interesante es el octavo punto:

sha1 para "dst"; 0 {40} si la creación, sin fusionar o "mira tree de trabajo".

Entonces en tu caso, obtienes 40 ceros, de modo que cualquiera de los dos significa "creación", "sin fusionar" o "mirar el tree de trabajo". Como solo tocó el file, y ya fue rastreado, puede eliminar las dos primeras opciones. Eso nos deja con "mirar el tree de trabajo" .

Y si haces eso, usando git diff (que intentará generar diferencias de contenido real para todos los cambios y, como tal, mirar el contenido del file), entonces Git aparentemente descubre que no hubo cambios después de todo, por lo que las llamadas subsiguientes ya no decir algo al respecto.

Esta observación me hace creer que por defecto git diff-index solo echará un vistazo rápido a los files, sin comparar realmente ningún contenido. Como ha modificado la date del file, Git lo considera como "posiblemente modificado" y requiere una apariencia más detallada para resolverlo correctamente.

Si ejecuta git diff-index con una opción que requiere que examine con mayor detenimiento los files, entonces tampoco encontrará ningún cambio, por ejemplo, al usar la opción -p para generar un parche (que es una especie de git diff hace).

Por lo tanto, es probable que solo una optimization del performance suponga que un file podría cambiarse si se cambiara la date de modificación del file, sin hacer afirmaciones reales al respecto; en su lugar, simplemente deja un marcador de "mira esto más adelante".