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 línea
diff --git a / builtin-http-fetch.cb / http-fetch.c
es un encabezado "git diff" en el formulario diff --git a/file1 b/file2. Los nombres de archivo a/y b/son los mismos a menos que se trate de renombrar / copiar (como en nuestro caso). Esto --gitsignifica que diff está en el formato diff "git".
A continuación hay una o más líneas de encabezado extendidas. Los primeros tres
índice de similitud 95%
cambiar el nombre de builtin-http-fetch.c
renombrar a http-fetch.c
díganos que se cambió el nombre del archivo builtin-http-fetch.ca http-fetch.cy 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
índice f3e63d7..e8f44ba 100644
cuéntenos sobre el modo del archivo dado ( 100644significa que es un archivo ordinario y no, por ejemplo, un enlace simbólico, y que no tiene un bit de permiso ejecutable), y sobre hash acortado de preimagen (la versión del archivo antes del cambio dado) y postimagen (el versión del archivo después del cambio). Esta línea se utiliza git am --3waypara intentar hacer una fusión de 3 vías si el parche no se puede aplicar por sí mismo.
El siguiente es el encabezado diff unificado de dos líneas
--- a / builtin-http-fetch.c
+++ b / http-fetch.c
En comparación con el diff -Uresultado, no tiene el tiempo de modificación de archivo ni el tiempo de modificación de archivo después de los nombres de los archivos de origen (imagen previa) y destino (imagen posterior). Si se creó el archivo, la fuente es /dev/null; si el archivo fue eliminado, el objetivo es /dev/null. Si se establece diff.mnemonicPrefixla variable de configuración de verdad, en lugar de a/y b/prefijos en esta cabecera de dos líneas que puede tener lugar c/, i/, w/y o/como prefijos, respectivamente, a lo que se compara; ver git-config (1)
Luego vienen uno o más trozos de diferencias; cada trozo muestra un área donde los archivos difieren. Los formatos unificados comienzan con líneas como
Está en el formato @@ from-file-range to-file-range @@ [header]. From-file-range tiene el formato -<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 la longitud del trozo en preimagen y postimagen, respectivamente. Si no se muestra el número de líneas, significa que es 0.
El encabezado opcional muestra la función C donde se produce cada cambio, si es un archivo C (como la -popción en GNU diff), o el equivalente, si lo hay, 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 izquierda:
'+': Aquí se agregó una línea al primer archivo.
'-' - Aquí se eliminó una línea del primer archivo.
@Geremia: Git utiliza heurísticas basadas en similitudes para la detección de cambio de nombre ... y también para el movimiento de código y la detección de copia git blame -C -C, así es como funciona; Es la decisión de diseño de Git. El formato git diff solo muestra el índice de similitud (o disimilitud) para el usuario.
Jakub Narębski
1
@Geremia: Para ser más exactos, [header]es el precedente más cercano, como el comienzo de la función que precede a un trozo. En la mayoría de los casos, esta línea incluye el nombre de la función en la que se encuentra el fragmento de diff. Esto es configurable con diffgitattribute establecido en el controlador diff, y el controlador diff incluyendo la xfuncnamevariable de configuración.
Jakub Narębski
1
@AnthonyGeoghegan: las líneas pueden eliminarse (el número de líneas en la imagen posterior es 0) o agregarse (el número de líneas en la imagen previa es 0).
Jakub Narębski
1
@KasunSiyambalapitiya: El formato de diferencias unificadas que utiliza Git (en oposición al formato de diferencias de contexto ^ [1]) no distingue entre la línea modificada y la línea eliminada y agregada. [1]: gnu.org/software/diffutils/manual/html_node/Context-Format.html
Jakub Narębski
1
@ JakubNarębski: El número de líneas predeterminado es 1, no 0. Es tan simple como eso. En la práctica, solo aparece como "-1" y / o "+1" para archivos de una sola línea porque no hay contexto para mostrar.
Guido Flohr
68
@@ -1,2 +3,4 @@ parte de la diferencia
Esta parte me llevó un tiempo comprender, así que he creado un ejemplo mínimo.
El formato es básicamente el mismo que el diff -udiff unificado.
-1,6significa que esta parte del primer archivo comienza en la línea 1 y muestra un total de 6 líneas. Por lo tanto, muestra las líneas 1 a 6.
1
2
3
4
5
6
-significa "viejo", como solemos invocarlo como diff -u old new.
+1,4significa que esta parte del segundo archivo comienza en la línea 1 y muestra un total de 4 líneas. Por lo 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 trozo es solo:
1
4
5
6
@@ -11,6 +9,4 @@ para 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 que la línea 11es la novena línea del nuevo archivo porque ya hemos eliminado 2 líneas en el trozo 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, func1() {en:
@@ -4,7 +4,6 @@ func1() {
Esto también se puede obtener con la -pbandera de la llanura diff.
Ejemplo: archivo antiguo:
func1() {
1;
2;
3;
4;
5;
6;
7;
8;
9;
}
Si eliminamos 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: omitió líneas 1y 2.
Esta característica impresionante a menudo dice exactamente a qué función o clase pertenece cada trozo, lo cual es muy útil para interpretar la diferencia.
Esto es para cualquiera que aún no lo haya entendido. En los @@ -1,6 +1,4 @@pls, no lea -1como minus oneo +1en su plus onelugar, lea esto como line 1 to 6en el archivo anterior (primero). Tenga en cuenta aquí - implies "old"no menos. Por cierto, gracias por la aclaración ... haash.
dkjain
a partir de esto @@ -1,8 +1,9 @@ es posible interpretar lo que realmente ha sucedido. por ejemplo 1) se ha agregado una línea 2) se está modificando una línea y se agrega una línea y así sucesivamente. O es de otra manera, ya que debería haber una forma de obtenerlos, ya que la corrección de git diff identifica qué líneas se han modificado en el código. Por favor,
ayúdenme,
Tenga en cuenta que es incorrecta y muy engañosa, esta afirmación en la respuesta anterior: " +1,4dice que esta pieza corresponde a las líneas 1 a 4 del segundo archivo ". Esto se debe a que +1,4puede referirse a líneas de contexto no contingentes. Más bien, lo que " +1,4" significa en realidad es que " hay 4líneas (es decir, líneas de contexto) en esa 'versión' del archivo ". Es importante entender el significado de la +, -y <whitespace>al principio de estas líneas, ya que se aplica a la interpretación de los trozos. Un ejemplo más visual: youtube.com/watch?v=1tqMjJeyKpw
Damilola Olowookere
23
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
--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 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 un enlace simbólico)
--- a/file +++ b/filelos 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 están presentes en b / (en mi caso --- significa líneas eliminadas y +++ significa líneas agregadas en b / y este 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 @@; supongamos que tiene el archivo line1 ... line100 y line10 eliminado 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
Gracias. "100644 son los bits de modo, lo que indica que este es un archivo normal (no ejecutable y no un enlace simbólico)". ¿Es "bits de modo" un concepto en Linux, o solo en Git?
Tim
@Tim No es específico de git. Los 3 dígitos correctos ( 644) deben leerse en octal (valores: 1, 2, 4 respectivamente permisos de Ejecución, Escritura y Lectura) y corresponden en ese orden al Propietario (Usuario), luego al Grupo, luego a Otros permisos. En resumen 644, significaría que si está escrito simbólicamente u=rw,og=r, eso es legible para todos, pero solo el propietario puede escribirlo. Los otros dígitos de la izquierda codifican otra información, como si se trata de un enlace simbólico, etc. Los valores se pueden ver en github.com/git/git/blob/… , el primer 1 en esta posición es "archivo normal".
Patrick Mevzek
15
El formato de salida predeterminado (que originalmente proviene de un programa conocido como diffsi 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 comienzan con un +,
líneas de eliminación, que comienzan con a -, y
líneas de metadatos que describen cosas de nivel superior, como de qué archivo está hablando, qué opciones se usaron para generar la diferencia, si el archivo cambió sus permisos, etc.
Le aconsejo que practique la lectura de diferencias entre dos versiones de un archivo donde sepa exactamente lo que cambió. Así reconocerás lo que está sucediendo cuando lo veas.
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:
Tenga en cuenta que git no imprime la parte 'XXX-FILE-MODIFICATION-TIME', ya que no tiene sentido para el sistema de control de versiones. Para comparar archivos en el sistema de archivos, las marcas de tiempo pueden funcionar como control de versión "pobre".
Jakub Narębski
3
No está claro a partir de su pregunta qué parte de los diferenciales encuentra confusa: la diferencia real o la información adicional del encabezado que imprime git. Por si acaso, aquí hay una descripción 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 es esta sección del diff. Si establece la variable de configuración booleana diff.mnemonic prefix, el ay bse cambiará a letras más descriptivas como cy w(commit y work tree).
A continuación, hay "líneas de modo": líneas que 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 index 789bd4..0afb621 100644. Probablemente nunca te importe, pero esos números hexadecimales de 6 dígitos son los hashes SHA1 abreviados de los blobs viejos y nuevos para este archivo (un blob es un objeto git que almacena datos sin procesar como el contenido de un archivo). Y, por supuesto, este 100644es el modo del archivo: los últimos tres dígitos son obviamente permisos; los primeros tres dan información adicional de metadatos del archivo ( publicación SO que describe eso ).
Después de eso, pasará a la salida diferencial unificada estándar (al igual que la clásica diff -U). Se divide en trozos: un trozo es una sección del archivo que contiene los cambios y su contexto. Cada trozo está precedido por un par de ---y +++líneas 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.
Respuestas:
Veamos un ejemplo de diferencia avanzada del historial de git (en commit 1088261f en el repositorio de git.git ):
Analicemos este parche línea por línea.
La primera línea
es un encabezado "git diff" en el formulariodiff --git a/file1 b/file2
. Los nombres de archivoa/
yb/
son los mismos a menos que se trate de renombrar / copiar (como en nuestro caso). Esto--git
significa que diff está en el formato diff "git".A continuación hay una o más líneas de encabezado extendidas. Los primeros tres
díganos que se cambió el nombre del archivobuiltin-http-fetch.c
ahttp-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 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 hash acortado de preimagen (la versión del archivo antes del cambio dado) y postimagen (el versión del archivo después del cambio). Esta línea se utilizagit am --3way
para intentar hacer una fusión de 3 vías si el parche no se puede aplicar por sí mismo.El siguiente es el encabezado diff unificado de dos líneas
En comparación con eldiff -U
resultado, no tiene el tiempo de modificación de archivo ni el tiempo de modificación de archivo después de los nombres de los archivos de origen (imagen previa) y destino (imagen posterior). Si se creó el archivo, la fuente es/dev/null
; si el archivo fue eliminado, el objetivo es/dev/null
.Si se establece
diff.mnemonicPrefix
la variable de configuración de verdad, en lugar dea/
yb/
prefijos en esta cabecera de dos líneas que puede tener lugarc/
,i/
,w/
yo/
como prefijos, respectivamente, a lo que se compara; ver git-config (1)Luego vienen uno o más trozos de diferencias; cada trozo muestra un área donde los archivos difieren. Los formatos unificados comienzan con líneas como
o Está en el formato@@ from-file-range to-file-range @@ [header]
. From-file-range tiene el formato-<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 la longitud del trozo en preimagen y postimagen, respectivamente. Si no se muestra el número de líneas, significa que es 0.El encabezado opcional muestra la función C donde se produce cada cambio, si es un archivo C (como la
-p
opción en GNU diff), o el equivalente, si lo hay, 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 izquierda:
Entonces, por ejemplo, primer trozo
significa que
cmd_http_fetch
fue reemplazado pormain
y queconst char *prefix;
se agregó esa línea.En otras palabras, antes del cambio, el fragmento apropiado del archivo 'builtin-http-fetch.c' se veía así:
Después del cambio, este fragmento del ahora archivo 'http-fetch.c' se ve así en su lugar:
Podría haber
línea presente (no es, por ejemplo, diff).Como dijo Donal Fellows , es mejor practicar diferencias de lectura en ejemplos de la vida real, donde sabes lo que has cambiado.
Referencias
fuente
git blame -C -C
, así es como funciona; Es la decisión de diseño de Git. El formato git diff solo muestra el índice de similitud (o disimilitud) para el usuario.[header]
es el precedente más cercano, como el comienzo de la función que precede a un trozo. En la mayoría de los casos, esta línea incluye el nombre de la función en la que se encuentra el fragmento de diff. Esto es configurable condiff
gitattribute establecido en el controlador diff, y el controlador diff incluyendo laxfuncname
variable de configuración.@@ -1,2 +3,4 @@
parte de la diferenciaEsta parte me llevó un tiempo comprender, así que he creado un ejemplo mínimo.
El formato es básicamente el mismo que el
diff -u
diff unificado.Por ejemplo:
Aquí eliminamos las líneas 2, 3, 14 y 15. Salida:
@@ -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 lo tanto, muestra las líneas 1 a 6.-
significa "viejo", como solemos invocarlo 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 lo 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 trozo es solo:
@@ -11,6 +9,4 @@
para el segundo trozo es análogo:en el archivo anterior, tenemos 6 líneas, comenzando en la línea 11 del archivo anterior:
en el nuevo archivo, tenemos 4 líneas, comenzando en la línea 9 del nuevo archivo:
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 trozo 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,func1() {
en:Esto también se puede obtener con la
-p
bandera de la llanuradiff
.Ejemplo: archivo antiguo:
Si eliminamos la línea
6
, la diferencia muestra:Tenga en cuenta que esta no es la línea correcta para
func1
: omitió líneas1
y2
.Esta característica impresionante a menudo dice exactamente a qué función o clase pertenece cada trozo, lo cual es muy útil para interpretar la diferencia.
La forma en que funciona exactamente el algoritmo para elegir el encabezado se analiza en: ¿De dónde proviene el extracto del encabezado git diff hunk?
fuente
@@ -1,6 +1,4 @@
pls, no lea-1
comominus one
o+1
en suplus one
lugar, lea esto comoline 1 to 6
en el archivo anterior (primero). Tenga en cuenta aquí- implies "old"
no menos. Por cierto, gracias por la aclaración ... haash.+1,4
dice que esta pieza corresponde a las líneas 1 a 4 del segundo archivo ". Esto se debe a que+1,4
puede referirse a líneas de contexto no contingentes. Más bien, lo que "+1,4
" significa en realidad es que " hay4
líneas (es decir, líneas de contexto) en esa 'versión' del archivo ". Es importante entender el significado de la+
,-
y<whitespace>
al principio de estas líneas, ya que se aplica a la interpretación de los trozos. Un ejemplo más visual: youtube.com/watch?v=1tqMjJeyKpwAquí está el ejemplo simple.
Aquí hay una explicación (ver 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 y b / está en el directorio de trabajo)10ff2df..84d4fa2
son ID de blob de estos 2 archivos100644
son los "bits de modo", que indican que se trata de un archivo normal (no ejecutable y no 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 las 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 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 @@
; supongamos que tiene el archivo line1 ... line100 y line10 eliminado y agrega una nueva línea100: obtendrá:fuente
644
) deben leerse en octal (valores: 1, 2, 4 respectivamente permisos de Ejecución, Escritura y Lectura) y corresponden en ese orden al Propietario (Usuario), luego al Grupo, luego a Otros permisos. En resumen644
, significaría que si está escrito simbólicamenteu=rw,og=r
, eso es legible para todos, pero solo el propietario puede escribirlo. Los otros dígitos de la izquierda codifican otra información, como si se trata de un enlace simbólico, etc. Los valores se pueden ver en github.com/git/git/blob/… , el primer 1 en esta posición es "archivo normal".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:+
,-
, yLe aconsejo que practique la lectura de diferencias entre dos versiones de un archivo donde sepa exactamente lo que cambió. Así reconocerás lo que está sucediendo cuando lo veas.
fuente
En mi mac:
info diff
luego seleccione:Output formats
->Context
->Unified format
->Detailed Unified
:O man diff en línea en gnu siguiendo la misma ruta a la misma sección:
fuente
No está claro a partir de su pregunta qué parte de los diferenciales encuentra confusa: la diferencia real o la información adicional del encabezado que imprime git. Por si acaso, aquí hay una descripción 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 es esta sección del diff. Si establece la variable de configuración booleanadiff.mnemonic prefix
, ela
yb
se cambiará a letras más descriptivas comoc
yw
(commit y work tree).A continuación, hay "líneas de modo": líneas que 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
index 789bd4..0afb621 100644
. Probablemente nunca te importe, pero esos números hexadecimales de 6 dígitos son los hashes SHA1 abreviados de los blobs viejos y nuevos para este archivo (un blob es un objeto git que almacena datos sin procesar como el contenido de un archivo). Y, por supuesto, este100644
es el modo del archivo: los últimos tres dígitos son obviamente permisos; los primeros tres dan información adicional de metadatos del archivo ( publicación SO que describe eso ).Después de eso, pasará a la salida diferencial unificada estándar (al igual que la clásica
diff -U
). Se divide en trozos: un trozo es una sección del archivo que contiene los cambios y su contexto. Cada trozo está precedido por un par de---
y+++
líneas 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.fuente
index
línea. Confirmado congit hash-object ./file