Solución:
Echemos un vistazo al ejemplo de diff avanzado del historial de git (en el compromiso 1088261f en el repositorio de git.git):
diff --git a/builtin-http-fetch.c b/http-fetch.c
similarity index 95%
rename from builtin-http-fetch.c
rename to http-fetch.c
index f3e63d7..e8f44ba 100644
--- a/builtin-http-fetch.c
+++ b/http-fetch.c
@@ -1,8 +1,9 @@
#include "cache.h"
#include "walker.h"
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
+int main(int argc, const char **argv)
{
+ const char *prefix;
struct walker *walker;
int commits_on_stdin = 0;
int commits;
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)
int get_verbosely = 0;
int get_recover = 0;
+ prefix = setup_git_directory();
+
git_config(git_default_config, NULL);
while (arg < argc && argv[arg][0] == '-') {
Analicemos este parche línea por línea.
-
La primera linea
diff --git a/builtin-http-fetch.c b/http-fetch.c
es un encabezado “git diff” con el formato
diff --git a/file1 b/file2
. losa/
yb/
los nombres de archivo son los mismos a menos que se trate de cambiar el nombre / copiar (como en nuestro caso). los--git
significa que diff está en el formato diff “git”. -
A continuación, se encuentran una o más líneas de encabezado extendidas. Los primeros tres
similarity index 95% rename from builtin-http-fetch.c rename to http-fetch.c
díganos que el nombre del archivo se cambió de
builtin-http-fetch.c
parahttp-fetch.c
y que esos dos archivos son 95% idénticos (que se utilizó para detectar este cambio de nombre).La última línea en el encabezado diff extendido, que es
index f3e63d7..e8f44ba 100644
cuéntenos sobre el modo del archivo dado (
100644
significa que es un archivo ordinario y no, por ejemplo, un enlace simbólico, y que no tiene un bit de permiso ejecutable), y sobre el hash abreviado de preimage (la versión del archivo antes del cambio dado) y postimage (la versión del archivo después del cambio). Esta línea es utilizada porgit am --3way
para intentar hacer una combinación de 3 vías si el parche no se puede aplicar por sí mismo. -
El siguiente es el encabezado diferencial unificado de dos líneas
--- a/builtin-http-fetch.c +++ b/http-fetch.c
En comparación con
diff -U
El resultado no tiene tiempo de modificación de archivo ni tiempo de modificación de archivo después de los nombres de archivo de origen (preimagen) y destino (postimagen). Si el archivo fue creado, la fuente es/dev/null
; si el archivo fue eliminado, el destino es/dev/null
.
Si ponesdiff.mnemonicPrefix
variable de configuración a verdadero, en lugar dea/
yb/
prefijos en este encabezado de dos líneas que puede tener en su lugarc/
,i/
,w/
yo/
como prefijos, respectivamente, a lo que compara; ver git-config (1) -
Luego vienen uno o más trozos de diferencias; cada trozo muestra un área donde los archivos difieren. Los trozos de formato unificado comienzan con una línea como
@@ -1,8 +1,9 @@
o
@@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, ...
Está en el formato
@@ from-file-range to-file-range @@ [header]
. El rango desde el archivo tiene la forma-<start line>,<number of lines>
y to-file-range es+<start line>,<number of lines>
. Tanto la línea de inicio como el número de líneas se refieren a la posición y longitud del trozo en preimagen y posimagen, respectivamente. Si no se muestra el número de líneas, significa que es 0.El encabezado opcional muestra la función C donde ocurre cada cambio, si es un archivo C (como
-p
opción en GNU diff), o el equivalente, si lo hubiera, para otros tipos de archivos. -
Luego viene la descripción de dónde difieren los archivos. 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 de la izquierda:
- ‘+’: Aquí se agregó una línea al primer archivo.
- ‘-‘ – Aquí se eliminó una línea del primer archivo.
Entonces, por ejemplo, primer fragmento
#include "cache.h" #include "walker.h" -int cmd_http_fetch(int argc, const char **argv, const char *prefix) +int main(int argc, const char **argv) { + const char *prefix; struct walker *walker; int commits_on_stdin = 0; int commits;
significa que
cmd_http_fetch
fue reemplazado pormain
, y esoconst char *prefix;
Se agregó la línea.En otras palabras, antes del cambio, el fragmento apropiado del archivo ‘builtin-http-fetch.c’ se veía así:
#include "cache.h" #include "walker.h" int cmd_http_fetch(int argc, const char **argv, const char *prefix) { struct walker *walker; int commits_on_stdin = 0; int commits;
Después del cambio, este fragmento del archivo ‘http-fetch.c’ ahora se ve así:
#include "cache.h" #include "walker.h" int main(int argc, const char **argv) { const char *prefix; struct walker *walker; int commits_on_stdin = 0; int commits;
-
Podría haber
No newline at end of file
línea presente (no está en el ejemplo diff).
Como dijo Donal Fellows, es mejor practicar la lectura de diferencias en ejemplos de la vida real, donde se sabe lo que ha cambiado.
Referencias:
- página de manual de git-diff (1), sección “Generación de parches con -p”
- (diff.info) Nodo unificado detallado, “Descripción detallada del formato unificado”.
@@ -1,2 +3,4 @@
parte de la diferencia
Me tomó un tiempo entender esta parte, así que he creado un ejemplo mínimo.
El formato es básicamente el mismo que el diff -u
diferencia unificada
Por ejemplo:
diff -u <(seq 16) <(seq 16 | grep -Ev '^(2|3|14|15)$')
Aquí eliminamos 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 @@
medio:
-
-1,6
significa que esta parte del primer archivo comienza en la línea 1 y muestra un total de 6 líneas. Por tanto, muestra las líneas 1 a 6.1 2 3 4 5 6
-
significa “antiguo”, ya que normalmente lo invocamos comodiff -u old new
. -
+1,4
significa que esta parte del segundo archivo comienza en la línea 1 y muestra un total de 4 líneas. Por tanto, muestra las líneas 1 a 4.+
significa “nuevo”.¡Solo tenemos 4 líneas en lugar de 6 porque se eliminaron 2 líneas! El nuevo galán es simplemente:
1 4 5 6
@@ -11,6 +9,4 @@
porque el segundo trozo es análogo:
-
en el archivo anterior, tenemos 6 líneas, comenzando en la línea 11 del archivo anterior:
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 esa línea
11
es la novena línea del nuevo archivo porque ya hemos eliminado 2 líneas en el trozo anterior: 2 y 3.
Encabezado de hunk
Dependiendo de su versión y configuración de git, también puede obtener una línea de código junto al @@
línea, por ejemplo, el func1() {
en:
@@ -4,7 +4,6 @@ func1() {
Esto también se puede obtener con el -p
bandera de llanura diff
.
Ejemplo: archivo antiguo:
func1() {
1;
2;
3;
4;
5;
6;
7;
8;
9;
}
Si quitamos la línea 6
, la diferencia 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
: saltó líneas 1
y 2
.
Esta asombrosa característica a menudo dice exactamente a qué función o clase pertenece cada trozo, lo cual es muy útil para interpretar la diferencia.
Cómo funciona exactamente el algoritmo para elegir el encabezado se discute en: ¿De dónde proviene el extracto en el encabezado de git diff hunk?
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 (vea los detalles aquí).
-
--git
no es un comando, esto significa que es una versión git de diff (no unix) -
a/ b/
son directorios, no son reales. es solo una conveniencia cuando tratamos con el mismo archivo (en mi caso, a / está en el índice yb / está en el directorio de trabajo) -
10ff2df..84d4fa2
son ID de blobs de estos 2 archivos -
100644
son los “bits de modo”, lo que indica que se trata de un archivo normal (no ejecutable ni un enlace simbólico) -
--- a/file +++ b/file
los signos menos muestran líneas en la versión a / pero faltan en la versión b /; y los signos más muestran líneas que faltan en a / pero están presentes en b / (en mi caso — significa líneas eliminadas y +++ significa líneas agregadas en b / y este es el archivo en el directorio de trabajo) -
@@ -1,5 +1,5 @@
para entender esto es mejor trabajar con un archivo grande; si tiene dos cambios en diferentes lugares, obtendrá dos entradas como@@ -1,5 +1,5 @@
; suponga que tiene el archivo line1 … line100 y eliminó la línea10 y agrega una nueva línea100; 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