La versión 2.19 de Git presenta git range-diff, que se supone que debe usarse para comparar dos rangos de confirmación. He estado leyendo la documentación, pero no puedo entender cuál es el propósito de estas nuevas características.

Revisé la documentación de Git oficial, y tengo problemas para entender su sintaxis (omitiendo banderas ):

git range-diff ( <range1> <range2> | <rev1>...​<rev2> | <base> <rev1> <rev2> )

¿Qué es rev1 y rev2?

¿Podría alguien explicar cuándo son útiles me refiero a cada caso?

git
8
lmiguelvargasf 14 sep. 2018 a las 02:23

4 respuestas

La mejor respuesta

Realmente no los he usado todavía, pero están pensados como una mejora sobre el antiguo flujo git cherry* para analizar / comparar algunos conjuntos de cambios aguas arriba o aguas abajo frente a lo que tiene ahora. Para que los conjuntos de rango sean útiles, queremos un conjunto de "aquí están mis confirmaciones" y "aquí están las suyas", expresadas de la manera más simple posible.

Un conjunto range1 range2 debería escribirse como, por ejemplo:

git range-diff theirs~5..theirs ours~4..ours

Si tuvieras, por ejemplo:

          T1--T2--T3--T4--T5   <-- theirs
         /
...--o--*   <-- base
         \
          O1--O2--O3--O4   <-- ours

Donde las confirmaciones O son "nuestras" y las confirmaciones T son "suyas".

Sin embargo, dada esta misma configuración, también podríamos escribir:

git range-diff theirs...ours    # or ours...theirs

(tenga en cuenta los tres puntos). (Esta es la sintaxis utilizada con git rev-list --cherry-mark --left-right, por ejemplo).

O, nuevamente dada esta misma situación, podríamos escribir:

git range-diff base theirs ours   # or base ours theirs

Aquí base es el punto de parada tanto para ellos como para los nuestros, y evita tener que contar 5.

Si la situación es más complicada, como en el gráfico:

          X1--T1--T2--T3   <-- theirs
         /
...--o--*   <-- base
         \
          Y1--Y2--O1--O2--O3--O4   <-- ours

Ni el tipo de sintaxis de tres puntos ni base ours theirs funciona bastante bien, por lo que los dos conjuntos de rangos (theirs~3..theirs ours~4..ours) serían los mejores.

9
torek 13 sep. 2018 a las 23:59

La diferencia de rango se vuelve muy útil justo después de resolver conflictos de fusión (después de rebase, cherry-pick, etc.),
especialmente cuando tuvo múltiples confirmaciones conflictivas y desea asegurarse de que no haya roto accidentalmente algo durante el proceso.

Aquí hay un escenario que generalmente ocurre en caso de que esté realizando múltiples confirmaciones en una rama.
Digamos que tenemos una rama llamada "nuestro", y nuestra rama está detrás de la rama maestra:

m1-m2-m3-m4  <- "master" branch
  \
   o1-o2-o3  <- "our" current branch

Antes de rehacer, hacemos una copia de seguridad de nuestra rama (acabo de hacer una copia de la rama con un nombre "our_bkp")

git branch our_bkp

Y ahora iniciamos un rebase con el maestro

git rebase master

Y resuelva algunos conflictos de fusión en el commit "o1" ...
Nota: si los archivos en conflicto en "o1" también se usaron / cambiaron en "o2" u "o3",
entonces tendremos que volver a resolver los mismos conflictos de fusión en ellos también.

Ahora, digamos, después de un agotador proceso de rebase tenemos algo como esto:

             _<- branch "master"
            /
 m1-m2-m3-m4-o1'-o2'-o3'  <- branch "our" (after rebase)
  \
   o1-o2-o3   <- branch "our_bkp"

Dado que hubo muchos conflictos de fusión, no es claramente visible si nos hemos perdido algo o no.

Y aquí es donde brilla la diferencia de rango.

Para asegurarnos de que no hemos perdido ningún cambio o dañado accidentalmente nada, simplemente podemos comparar nuestras confirmaciones de la versión anterior de la rama con la versión más nueva:

git range-diff our_bkp~3..our_bkp our~3..our

O

git range-diff o1..o3 o1'..o3'

Si las diferencias solo están relacionadas con las partes en conflicto, entonces estamos bien y no hemos cambiado nada más que ellas.
Pero si vemos otras diferencias inesperadas, entonces nosotros o git hicimos algo mal, y tendremos que arreglarlas.

Notas

  • Los dos comandos range-diff anteriores están haciendo exactamente lo mismo.
  • Al decir o1..o3 me refiero a los números de esas confirmaciones, por ejemplo: 0277a5883d132bebdb34e35ee228f4382dd2bb7..e415aee3fa53a213dc53ca6a7944301066b72f24
  • El ~3 en our_bkp~3 dice git para tomar el commit que fue 3 commits antes del último en la rama our_bkp. Reemplace el número con la cantidad de confirmaciones que tenía en su sucursal y, por supuesto, no olvide reemplazar el nombre de la sucursal our_bkp con el nombre de su sucursal de respaldo.
2
Just Shadow 16 abr. 2020 a las 11:35

El comando git range-diff, que puede ver aquí comparando dos parches, se ha revisado en Git 2.23 (Q3 2019), para una identificación más fácil de qué parte del archivo se trata el parche que se muestra .

Consulte commit 499352c, commit 444e096, commit 430be36, commit e1db263, commit 44b67cb, commit 1ca6922, commit ef283b3, commit 80e1841 (11 de julio de 2019) y commit 877a833, cometer 570fe99, commit 85c3713, commit d6c88c4 = "https://github.com/git/git/commit/5af40877a4354156b311060eb6594cb5159e0577" rel = "nofollow noreferrer"> commit 5af4087 (08 de julio de 2019) por Thomas Gummerer (tgummerer).
(Fusionada por Junio ​​C Hamano - gitster - en commit 43ba21c, 25 de julio de 2019)

range-diff: agrega el nombre del archivo a la diferencia interna

En un rango-diff no siempre está claro qué archivo un determinado funcname de el diff interno pertenece, porque el encabezado diff (o el encabezado de sección agregado en un commit anterior) no siempre es visible en el rango-diff.

Agregue el nombre de archivo al encabezado diffs interno, para que siempre esté visible para los usuarios.

Esto también nos permite agregar el nombre de archivo + el nombre de función a los encabezados de trozos de diferencias externas utilizando un patrón de diferencia de usuario personalizado, que se realizará en la próxima confirmación.

range-diff: agrega encabezados al encabezado del trozo externo

Agregue los encabezados de sección / encabezados de trozos que presentamos en los commits anteriores a los encabezados de trozos del diff externo.
Esto hace que sea más fácil entender qué cambio estamos viendo realmente. Por ejemplo, un encabezado de trozo externo ahora podría verse así:

@@  Documentation/config/interactive.txt

mientras que anteriormente solo hubiera sido

@@

lo que no da mucho contexto para el cambio que sigue.

Consulte t3206-range-diff.sh como ejemplo.

Y:

range-diff: agregar encabezado de sección en lugar de encabezado diff

Actualmente, range-diff mantiene intacto el encabezado diff del diff interno (aparte de las líneas de separación que comienzan con el índice).
Este encabezado diff es algo útil, especialmente cuando los archivos son diferentes nombres en diferentes rangos.

Sin embargo, no hay necesidad real de mantener todo el encabezado diff para eso.
La razón principal por la que lo hacemos actualmente es probablemente porque es fácil de hacer.

Introduzca un nuevo encabezado de hunk diff de rango, que está encerrado por "##", similar a cómo los números de línea en hunk diff están encerrados por "@@", y brinde información legible por humanos de lo que sucedió exactamente en el archivo , incluido el nombre del archivo.

Esto mejora la legibilidad de la diferencia de rango al dar más conciso información a los usuarios.
Por ejemplo, si se cambia el nombre de un archivo en una iteración, pero no en otra, la diferencia de los encabezados sería bastante ruidosa.
Sin embargo, la diferencia de una sola línea es concisa y debería ser más fácil de entender.

Nuevamente, t3206-range-diff.sh <{X0}} <{X0}} <{X0}} <{X0}} proporciona un ejemplo:

git range-diff --no-color --submodule=log topic...renamed-file >actual &&
sed s/Z/\ /g >expected <<-EOF &&
1:  4de457d = 1:  f258d75 s/5/A/
2:  fccce22 ! 2:  017b62d s/4/A/
    @@ Metadata
    ZAuthor: Thomas Rast <trast@inf.ethz.ch>
    Z
    Z ## Commit message ##
    -    s/4/A/
    +    s/4/A/ + rename file
    Z
    - ## file ##
    + ## file => renamed-file ##
    Z@@
    Z 1
    Z 2

Pero: tenga cuidado con el diff.noprefix configuración: ¡A git range-diff sería predeterminado con Git antes de 2.24 (Q4 2019)!

"git range-diff" se configuró por defecto cuando se utilizó la configuración diff.noprefix, ya que esperaba ciegamente que el parche que genera internamente tenga los prefijos estándar a/ y b/.
El comando ahora obliga a construir el parche interno sin ningún prefijo, para que no se vea afectado por ninguna configuración del usuario final.

Consulte commit 937b76e (02 de octubre de 2019) por Johannes Schindelin (dscho).
(Fusionada por Junio C Hamano - gitster - en commit 159cdab, 11 de octubre de 2019)

range-diff: fuerza interna diff.noprefix=true

Al analizar las diferencias, range-diff espera ver los prefijos a/ y b/ en los encabezados de diferencias.

Estos prefijos se pueden forzar mediante la configuración diff.noprefix=true.
Como range-diff no está preparado para esa situación, esto causará una falla de segmentación.

Evitemos eso pasando la opción --no-prefix al proceso git log que genera los diferenciales que range-diff quiere analizar.
Y, por supuesto, esperar que la salida no tenga prefijos, entonces.


Y "git range-diff" no pudo manejar el cambio de modo solo , que ha sido corregido con Git 2.24 (Q4 2019):

Ver commit 2b6a9b1 (08 oct 2019) por Thomas Gummerer (tgummerer).
(Fusionada por Junio C Hamano - gitster - en commit b6d712f, 15 de octubre de 2019)

range-diff: no segfault con cambios de solo modo

Reportado por: Uwe Kleine-König
Firmado por: Thomas Gummerer
Acked-by: Johannes Schindelin

En ef283b3699 ("apply: hacer parse_git_diff_header público" , 2019-07-11, Git v2.23.0-rc0 - merge listado en lote # 7) la función 'parse_git_diff_header' se hizo pública y utilizable por personas que llaman fuera de apply.c.

Sin embargo, se omitió que su (entonces) único llamador, 'find_header' realizó un manejo de errores y completó 'struct patch' adecuadamente.

range-diff luego comenzó a usar esta función y trató de manejar esto apropiadamente, pero se quedó corto en algunos casos.

Esto a su vez conduciría a range-diff segfaulting cuando hay cambios de solo modo en un rango .

Mueva el manejo de errores y la finalización de la estructura a la función 'parse_git_diff_header', para que otros llamantes puedan aprovecharla.

Esto corrige la segfault en 'git range-diff'.


Con Git 2.25 (Q1 2020), "git range-diff" aprendió a tomar las opciones "--notes=<ref>" y "--no-notes" para controlar las notas de confirmación incluidas en el mensaje de registro que se compara.

Consulte commit 5b583e6, commit bd36191, commit 3bdbdfb, commit 75c5aa0, commit 79f3950, commit 3a6e48e, "https://github.com/git/git/commit/26d94853f083425872a27d525556cf8bcdfe 67ba "rel =" nofollow noreferrer ">commit 26d9485 (20 de noviembre de 2019) y commit 9d45ac4, commit 828e829 (19 nov 2019) por Denton Liu (Denton-L).
(Fusionada por Junio ​​C Hamano - gitster - en commit f3c7bfd, 05 dic 2019)

range-diff: salida ## Notes ## encabezado

Firmado por: Denton Liu

Cuando se incluyeron notas en la salida de range-diff, se combinaron con el resto del mensaje de confirmación. Como resultado, los usuarios no podrían distinguir claramente dónde terminó el mensaje de confirmación y dónde comenzaron las notas.

Imprima un encabezado ## Notes ## cuando se detectan notas para que las notas se puedan comparar con mayor claridad.

Tenga en cuenta que también manejamos el caso de Notes (<ref>): -> ## Notes (<ref>) ## con este código. Sin embargo, no podemos probar esto en este parche, ya que actualmente no hay forma de pasar diferentes referencias de notas a git log. Esto se solucionará en un parche futuro.

Y:

Consulte commit abcf857, commit f867534, Denton Liu (Denton-L). < br /> (Fusionada por Junio C Hamano - gitster - en commit d1c0fe8, 16 dic 2019)

range-diff: claro other_arg al final de la función

Firmado por: Denton Liu

Estábamos perdiendo memoria al no borrar other_arg después de haber terminado de usarlo.
Bórralo después de que hayamos terminado de usarlo.

Tenga en cuenta que esto no es estrictamente necesario ya que la memoria se recuperará una vez que el comando salga.
Sin embargo, dado que estamos lanzando strbufs, también deberíamos borrar other_arg para mantener la coherencia.


Con Git 2.27 (Q2 2020), "git range-diff" es más robusto.

Consulte commit 8d1675e, commit 8cf5156 (15 de abril de 2020) por Vasil (vasild).
(Fusionada por Junio C Hamano - gitster - en commit 93d1f19, 28 de abril de 2020)

range-diff: corrige un bloqueo en el análisis git-log salida

Firmado por: Vasil Dimov

git range-diff llama a git log internamente e intenta analizar su salida.

Pero el usuario puede personalizar la salida de git log en su git config y para ciertas configuraciones, git range-diff devolverá un error o se bloqueará.

Para solucionar esto, configure explícitamente el formato de salida del git log ejecutado internamente con --pretty=medium.
Como eso cancela --notes, agregue explícitamente --notes al final.

Además, asegúrese de que nunca nos bloqueemos de la misma manera, tratando de desreferenciar util que nunca se creó y que ha permanecido NULL.
Ocurriría si la primera línea de salida git log no comienza con 'commit'.

Alternativa considerada pero descartada: de alguna manera deshabilite todas las configuraciones de git y compórtese como si no hubiera ninguna configuración en git log ejecutado internamente, pero eso no parece ser posible.
GIT_CONFIG_NOSYSTEM es el más cercano a él, pero incluso con eso todavía leeríamos .git/config.

1
VonC 1 may. 2020 a las 22:10

Un "rango" en el lenguaje Git es un par de identificadores de revisión (inicio y fin).

La primera forma de uso para git range-diff es <range1> <range2>. Como sabemos que un rango es un par de identificadores de revisión, algunos ejemplos posibles son:

abc1234..def5678 9876foo..5432bar
HEAD..def5678 my_release_1_1..my_release_1_2

Las otras dos formas de uso son convenientes cuando algunos de los cuatro identificadores de revisión son iguales entre sí. A saber:

  1. Para un caso como abc..def def..abc, simplemente puede especificar def...abc.
  2. Para un caso como abc..def abc..xyz, puede especificar abc def xyz. Esto me parece un caso común: desea comparar dos rangos que comienzan en el mismo punto.
3
John Zwinck 14 sep. 2018 a las 10:56