tag - lista de comandos git




¿Cómo leer la salida de git diff? (5)

Aquí está el ejemplo simple.

diff --git a/file b/file 
index 10ff2df..84d4fa2 100644
--- a/file
+++ b/file
@@ -1,5 +1,5 @@
 line1
 line2
-this line will be deleted
 line4
 line5
+this line is added

Aquí hay una explicación (ver detalles here ).

  • --git no es un comando, esto significa que es una versión de git de diff (no unix)
  • a/ b/ son directorios, no son reales. es solo una comodidad cuando tratamos con el mismo archivo (en mi caso a / está en el índice y b / está en el directorio de trabajo)
  • 10ff2df..84d4fa2 son ID de blob de estos 2 archivos
  • 100644 son los "bits de modo" que indican que se trata de un archivo normal (no ejecutable y no es un enlace simbólico)
  • --- a/file +++ b/file signos menos muestran líneas en la versión a / pero faltan en la versión b /; y los signos más muestran las líneas que faltan en a / pero presentes en b / (en mi caso --- significa líneas eliminadas y +++ significa líneas agregadas en b / y esto el archivo en el directorio de trabajo)
  • @@ -1,5 +1,5 @@ para comprender esto, es mejor trabajar con un archivo grande; si tiene dos cambios en lugares diferentes, obtendrá dos entradas como @@ -1,5 +1,5 @@ ; Supongamos que tiene el archivo line1 ... line100 y el line10 eliminado y agrega un nuevo line100: obtendrá:
@@ -7,7 +7,6 @@ line6
 line7
 line8
 line9
-this line10 to be deleted
 line11
 line12
 line13
@@ -98,3 +97,4 @@ line97
 line98
 line99
 line100
+this is new line100

La página de manual de git-diff es bastante larga y explica muchos casos que no parecen ser necesarios para un principiante. Por ejemplo:

git diff origin/master

El formato de salida predeterminado (que originalmente proviene de un programa conocido como diff si desea buscar más información) se conoce como "diff unificado". Contiene esencialmente 4 tipos diferentes de líneas:

  • líneas de contexto, que comienzan con un solo espacio,
  • líneas de inserción que muestran una línea que se ha insertado, que comienza con un + ,
  • líneas de eliminación, que comienzan con una - , y
  • líneas de metadatos que describen cosas de nivel superior como de qué archivo se está hablando, qué opciones se usaron para generar el diff, si el archivo cambió sus permisos, etc.

Le aconsejo que practique la lectura de diferencias entre dos versiones de un archivo en el que sepa exactamente lo que cambió. Así reconocerás lo que está sucediendo cuando lo veas.


En mi mac

info diff luego seleccione: Output formats -> Context -> Unified format -> Detailed Unified :

O en línea man diff en gnu siguiendo el mismo camino a la misma sección:

Archivo: diff.info, Nodo: Detallado Unificado, Siguiente: Ejemplo Unificado, Hasta: Formato Unificado

Descripción detallada del formato unificado ......................................

El formato de salida unificado comienza con un encabezado de dos líneas, que se ve así:

 --- FROM-FILE FROM-FILE-MODIFICATION-TIME
 +++ TO-FILE TO-FILE-MODIFICATION-TIME

La marca de tiempo se ve como `2002-02-21 23: 30: 39.942229878 -0800 'para indicar la fecha, la hora con segundos fraccionarios y la zona horaria.

Puede cambiar el contenido del encabezado con la opción `--label = LABEL '; ver * Nota Nombres alternativos ::.

Luego vienen uno o más trozos de diferencias; Cada trozo muestra un área donde los archivos difieren. Los trozos de formato unificado se ven así:

 @@ FROM-FILE-RANGE TO-FILE-RANGE @@
  LINE-FROM-EITHER-FILE
  LINE-FROM-EITHER-FILE...

Las líneas comunes a ambos archivos comienzan con un carácter de espacio. Las líneas que realmente difieren entre los dos archivos tienen uno de los siguientes caracteres indicadores en la columna de impresión izquierda:

`+ 'Aquí se agregó una línea al primer archivo.

`- 'Se eliminó una línea aquí del primer archivo.


No queda claro a partir de su pregunta qué parte de las diferencias le resultan confusas: la diferencia realmente, o la información adicional del encabezado que imprime git. Por si acaso, aquí hay una descripción general rápida del encabezado.

La primera línea es algo así como diff --git a/path/to/file b/path/to/file - obviamente solo te dice para qué archivo está esta sección del diff. Si configura la variable de configuración booleana diff.mnemonic prefix , a y b se cambiarán a letras más descriptivas como c y w (commit y work tree).

A continuación, hay "líneas de modo": líneas que le proporcionan una descripción de cualquier cambio que no implique cambiar el contenido del archivo. Esto incluye archivos nuevos / eliminados, archivos renombrados / copiados, y cambios de permisos.

Finalmente, hay una línea como el index 789bd4..0afb621 100644 . Probablemente nunca se preocupará por eso, pero esos números hexadecimales de 6 dígitos son los hashes SHA1 abreviados de los blobs antiguos y nuevos para este archivo (un blob es un objeto git que almacena datos en bruto como el contenido de un archivo). Y, por supuesto, el 100644 es el modo del archivo: los últimos tres dígitos son, obviamente, permisos; los tres primeros proporcionan información adicional sobre los metadatos del archivo ( mensaje SO que describe eso ).

Después de eso, está en la salida estándar de diff unificada (al igual que el clásico diff -U ). Se divide en trozos: un trozo es una sección del archivo que contiene los cambios y su contexto. Cada fragmento está precedido por un par de líneas --- y +++ que denotan el archivo en cuestión, luego la diferencia real es (por defecto) tres líneas de contexto a cada lado de las líneas - y + que muestran las líneas eliminadas / agregadas .


@@ -1,2 +3,4 @@ parte de la diferencia

Esta parte me tomó un tiempo para entender, así que he creado un ejemplo mínimo.

El formato es básicamente el mismo el diff -u unified diff.

Por ejemplo:

diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')

Aquí quitamos las líneas 2, 3, 14 y 15. Salida:

@@ -1,6 +1,4 @@
 1
-2
-3
 4
 5
 6
@@ -11,6 +9,4 @@
 11
 12
 13
-14
-15
 16

@@ -1,6 +1,4 @@ significa:

  • -1,6 : esta pieza corresponde a la línea 1 a 6 del primer archivo:

    1
    2
    3
    4
    5
    6
    

    - significa "viejo", ya que usualmente lo invocamos como diff -u old new .

  • +1,4 dice que esta pieza corresponde a la línea 1 a 4 del segundo archivo.

    + significa "nuevo".

    ¡Solo tenemos 4 líneas en lugar de 6 porque se eliminaron 2 líneas! El nuevo trozo es solo:

    1
    4
    5
    6
    

@@ -11,6 +9,4 @@ para el segundo fragmento es análogo:

  • en el archivo anterior, tenemos 6 líneas, comenzando en la línea 11 del archivo antiguo:

    11
    12
    13
    14
    15
    16
    
  • En el nuevo archivo, tenemos 4 líneas, comenzando en la línea 9 del nuevo archivo:

    11
    12
    13
    16
    

    Tenga en cuenta que la línea 11 es la novena línea del nuevo archivo porque ya hemos eliminado 2 líneas en el fragmento anterior: 2 y 3.

Encabezado Hunk

Dependiendo de su versión y configuración de git, también puede obtener una línea de código junto a la línea @@ , por ejemplo, la func1() { en:

@@ -4,7 +4,6 @@ func1() {

Esto también se puede obtener con la bandera -p de plain diff .

Ejemplo: archivo antiguo:

func1() {
    1;
    2;
    3;
    4;
    5;
    6;
    7;
    8;
    9;
}

Si eliminamos la línea 6 , el diff muestra:

@@ -4,7 +4,6 @@ func1() {
     3;
     4;
     5;
-    6;
     7;
     8;
     9;

Tenga en cuenta que esta no es la línea correcta para func1 : omitió las líneas 1 y 2 .

Esta característica impresionante a menudo indica exactamente a qué función o clase pertenece cada persona, lo que es muy útil para interpretar la diferencia.

El modo en que el algoritmo para elegir el encabezado funciona exactamente se explica en: ¿De dónde proviene el extracto en el encabezado de git diff hunk?





git-diff