Git log explicado

Para un visor de logging de git que estoy construyendo, solo estaba viendo la salida de git log y me preguntaba sobre tres cosas. Como no hay documentation sobre el resultado exacto en el libro de Git SCM y resources similares disponibles, tuve que preguntar en SO:

  1. ¿Cuál es el index 1234567..1234567 123456 ? No coincide con los commits sha ?
  2. ¿Cuál es el int después de la coma para una línea modificada? @@ -40,20 +40,20 @@ ?
  3. ¿Cuál es la parte después del segundo @@ para una línea modificada?

Ejemplo, tomado de Git SCM Book "Visualización del historial de confirmaciones"

 $ git log -p -2 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon[email protected]> Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 --- a/Rakefile +++ b/Rakefile @@ -5,5 +5,5 @@ require 'rake/gempackagetask' spec = Gem::Specification.new do |s| s.name = "simplegit" - s.version = "0.1.0" + s.version = "0.1.1" s.author = "Scott Chacon" s.email = "[email protected] 

1. ¿Cuál es el índice 1234567..1234567 123456? No coincide con los commits sha?

De la página man de git-log :

La línea de índice incluye la sum de comprobación SHA-1 antes y después del cambio. El <modo> está incluido si el modo de file no cambia; de lo contrario, las líneas separadas indican el modo antiguo y el nuevo.

De acuerdo, genial … pero ¿qué significa eso?

Entonces, git funciona almacenando objects internamente usando direcciones. Estas sums de comprobación SHA-1 son las direcciones para las versiones de file antes y después de su cambio.

Puedes ver eso usando un command git-internal para acceder a esos files:

 $git cat-file -p a874b73 <--- the contents of the file before the commit ---> $git cat-file -p 8f94139 <--- the contents of the file after the commit ---> 

El segundo número, el <mode> , indica los permissions del file Unix. Consulte esta respuesta para get más información sobre cómo leerlos .

¡Vea a continuación un ejemplo que explica los hashes!

EDITAR: Vaya, se olvidó de abordar la segunda y la tercera pregunta.

2. ¿Cuál es el int después de la coma para una línea modificada? @@ -40,20 +40,20 @@?

Los cambios se muestran usando el formatting unificado de diferencias . Ese artículo de wikipedia tiene una explicación bastante buena, pero básicamente esa línea es la range information . Consiste en dos pares: el primer par tiene un signo - y el segundo par un signo + . El par se refiere al file original y el par + al segundo file. En cada par, el primer número es el número de la línea de inicio del fragment a punto de mostrarse, y el segundo número es la cantidad de líneas que se mostrarán.

Entonces @@ -10,5 +10,10 @@

Significaría que ha agregado 5 líneas y, por lo tanto, el trozo tiene 5 líneas más en la segunda versión.

3. ¿Cuál es la parte después del segundo @@ para una línea modificada?

Se supone que esta línea es el context en el que se encuentra el fragment. Por lo tanto, como señala la respuesta de @ TimWolla a continuación, si se tratara de un progtwig C / C ++, ese podría ser el nombre de la function en la que se encuentra este fragment. En este caso, la línea require 'rake/gempackagetask' Ruby es probablemente la primera línea del progtwig, por lo que diff pensó que era un nombre apropiado para referirse a esta sección.


Aquí hay un par de ejemplos de la sum de comprobación SHA-1 de git en el trabajo:

 $ touch newfileA newfileB $ git add newfile* $ git commit -m 'added new files' [master a49cb1c] added new files 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 newfileA create mode 100644 newfileB $ git log -p -1 commit a49cb1c5292082a6ed9c7f09e1bce2636e60ab93 Author: Nathan Daly <[email protected]> Date: Sat Mar 1 16:10:49 2014 -0500 added new files diff --git a/newfileA b/newfileA new file mode 100644 index 0000000..e69de29 diff --git a/newfileB b/newfileB new file mode 100644 index 0000000..e69de29 

Puede ver que antes de la confirmación los files no existían (porque no hay una dirección que se refiera a una versión anterior: por lo tanto, el índice 0000000), y después de que se crearon, los blobs para esos files tienen la dirección e69de29. Comparten el mismo hash, porque los files son idénticos, por lo que no hay ninguna razón para tener copys diferentes de un file vacío.

Puedes ver esto simplemente haciendo un hash con un file vacío. Obtenemos el mismo hash que antes (esta vez en toda su longitud):

 $ touch blankfile $ git hash-object blankfile e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 

Ahora, si cambiamos el contenido de los files:

 $ echo 'contents1' > newfileA $ echo 'contents2' > newfileB $ git add newfile* $ git commit -m 'updated newfile contents' [master 76827d7] updated newfile contents 2 files changed, 2 insertions(+) $ git log -p -1 commit 76827d7af1846c6c0f07ac2b78771cbc34cd6056 Author: Nathan Daly <[email protected]> Date: Sat Mar 1 16:18:40 2014 -0500 updated newfile contents diff --git a/newfileA b/newfileA index e69de29..a024003 100644 --- a/newfileA +++ b/newfileA @@ -0,0 +1 @@ +contents1 diff --git a/newfileB b/newfileB index e69de29..6b46faa 100644 --- a/newfileB +++ b/newfileB @@ -0,0 +1 @@ +contents2 

Puedes ver que ahora tienen hashes diferentes. Cada uno de ellos comenzó desde el object en e69de29 y se movió a un nuevo object con una dirección diferente. Y, para verificar eso, podemos get los contenidos de esos objects de sus hashes respectivos:

 $ git cat-file -p a024003 contents1 $ git cat-file -p 6b46faa contents2 

Finalmente, si volviéramos a igualar su contenido, compartirían una vez más un hash. (De nuevo, git hace esto solo para ahorrar espacio en el disco, ya que los dos files son idénticos, pero para el nombre)

 $ echo 'contents2' > newfileA $ git add newfileA $ git commit -m 'now files match' $ git log -p -1 commit 3f63bcef9290fae616521ec1b380639c6026c5c5 Author: Nathan Daly <[email protected]> Date: Sat Mar 1 16:22:29 2014 -0500 now files match diff --git a/newfileA b/newfileA index a024003..6b46faa 100644 --- a/newfileA +++ b/newfileA @@ -1 +1 @@ -contents1 +contents2 

Como puede ver, ahora newfileA también tiene hash 6b46faa , al igual que newfileB.

Cada object en git se almacena con dicha dirección hash, por lo que en su aplicación git log viewer, puede usar esos hash de índice para mostrar al usuario el contenido del file en cada una de esas versiones.

Para responder las preguntas no manejadas por la respuesta de NHDaly:

¿Cuál es el int después de la coma para una línea modificada? @@ -40,20 +40,20 @@?

Es la longitud (las líneas sin a + o - más el número de líneas con a - para la primera y el número de líneas con a + para la segunda) del bloque que sigue. En este caso: el número de líneas visualizadas es 20 .

¿Cuál es la parte después del segundo @@ para una línea modificada?

diff utiliza un algorithm que determina el context, funciona mejor para el código C, donde debe mostrar el encabezado del método, ver por ejemplo Commit af87d2fe95 del kernel de Linux .

Como una adición a las otras respuestas (excelentes), aquí hay algunos ejemplos más detallados sobre las líneas añadidas / eliminadas, ya que el formatting de diferencia unificada no implica que el valor de la coma sea 1 (línea agregada / eliminada). Esto significa que ningún valor de coma no significa null , pero 1 y cero / 0 no significa null , sino 1 . Esto podría confundir a algunos progtwigdores como yo.

Ejemplos

Los siguientes ejemplos implican que está llamando a git show --unified=0 $sha y no muestra las líneas sin cambios. Otras líneas sin cambios se includeán como TimWolla señaló en los comentarios (gracias).

 @@ -10,5 +10,10 @@ 

Significa que hubo 5 líneas eliminadas y 10 líneas agregadas.

 @@ -10,0 +10,2 @@ 

No se eliminaron líneas, pero se agregaron 2 líneas.

 @@ -10 +10,2 @@ 

Se eliminó una línea y se agregaron 2 líneas.

 @@ -10 +10 @@ 

Se eliminó una línea y se agregó 1 línea.

 @@ -10,7 +10 @@ 

Se eliminaron 7 líneas y se agregó 1 línea.

 @@ -10,7 +10,0 @@ 

Se eliminaron 7 líneas y no se agregaron líneas.