2011-12-20 16 views
18

¿Hay alguna forma de comprobar si dos diffs o parches son equivalentes?¿Hay alguna forma de comparar dos diffs o parches?

Digamos que tiene la siguiente git commit historia, donde las características F y G son limpiamente rebaseable a E:

 G 
    /
A--B--C--D--E 
\ 
    F 

Debido a limitaciones en nuestro proceso de implementación actual, tenemos lo siguiente, de alguna manera relacionado gráfico (no es versión controlada)

   G' 
      /
------------E' 
      \ 
       F' 

F 'y G' en última instancia ser aplicado a la cabeza e', en algunos como orden determinado, por lo que terminaría como

------------E'--G'--F' 

¿Hay alguna manera de probar que la diferencia de E 'a G' es la misma que la del parche producido por el compromiso de git de G?

Me doy cuenta totalmente de que en un mundo ideal, el control de revisiones resolvería esto, y estamos llegando allí, pero no es donde estamos actualmente.

En esencia, podría reproducir ambos parches en cajas separadas y comparar las salidas, pero eso parece un poco torpe. Y comparando los diferenciales, supongo, no funcionaría porque los números de línea podrían cambiar. Incluso si G 'y F' se rebasaran a E ', el parche para F' se aplicaría finalmente a G ', lo que haría diferente el contexto del parche.

+2

¿Usted intentó un diff en los diferenciales? – Geoffroy

+0

Gnu diff tiene un interruptor de línea de comando para especificar expresiones regulares para que las líneas sean ignoradas cuando se genera la diferencia. – holygeek

+0

Para lotes, 'git patch-id' y' git cherry' (también vea las opciones '--cherry *' para git log) pueden usarse como respuesta rápida, pero es demasiado estricto y puede considerar importantes cambios menores. Diferencia de diffs es el camino a seguir cuando necesita cierta respuesta – max630

Respuesta

1

me acaba de dejar git intentar probar:

git checkout E -b FG 
git cherry-pick F' G' 
git checkout E -b GF 
git cherry-pick G' F' 
git diff FG GF 
git branch -D FG GF 
+0

Las confirmaciones "principales" no están en control de versión. En realidad no son commits, son parches basados ​​en los commits reales E y F. Pero pueden o no estar contaminados con algunos otros datos (que es lo que estoy probando). –

+0

¿Podría aplicar los parches? Diffs no están hechos para ser diferidos, pero git es realmente bueno en eso. Tal vez una situación de martillo/clavo, pero estoy seguro de que funcionaría. :) – dahlbyk

+0

¿Qué quiere decir con "simplemente aplicar los parches"? Tengo dos diferencias y solo quiero aplicar el parche si son equivalentes. Si no, el parche no debe aplicarse en absoluto. –

23
diff <(git show COMMIT1SHA) <(git show COMMIT2SHA) 
+2

¿Puedes agregar un contexto sobre cómo responde esto a la pregunta? – Chrismas007

+1

Compara (diffs) dos diffs (en este caso las diffs de dos commits diferentes). – mrbrdo

+1

Hace una diferencia de los cambios reales que realizaron las confirmaciones, así como los metadatos de las confirmaciones (sha, autor, fecha, mensaje de confirmación, etc.). Lo he usado para verificar si dos confirmaciones en sucursales separadas introducen el mismo cambio, para estar seguro de que puedo usar cualquiera de ellas para una selección inteligente. –

0

Para beneficio del lector, aquí es una actualización de the answer of @mrbrdo con un pequeño arreglo:

  • Añade git sdiff alias para un fácil acceso de esto. sdiff significa show diff.
  • Ignore los encabezados de etiqueta anotados utilizando el sufijo ^{}.
  • diff Permitir opciones para ser utilizados como -u etc.

Ejecutar esta vez en cada una de sus cuentas en las que utilice git:

git config --global alias.sdiff '!'"bash -c 'O=(); A=(); while x=\"\$1\"; shift; do case \$x in -*) O+=(\"\$x\");; *) A+=(\"\$x^{}\");; esac; done; g(){ git show \"\${A[\$1]}\" && return; echo FAIL \${A[\$1]}; git show \"\${A[\$2]}\"; }; diff \"\${O[@]}\" <(g 0 1) <(g 1 0)' --" 

Después se puede utilizar esto:

git sdiff F G 

Tenga en cuenta que esto necesita bash versión 3 o superior.

Explicación:

  • git config --global alias.sdiff añade un alias llamado git sdiff en el mundial ~/.gitconfig.

  • ! corre el alias como comando shell

  • bash -c necesitamos bash (o ksh), como <(..) no funciona en dash (aka. /bin/sh).

  • O=(); A=(); while x="$1"; shift; do case $x in -*) O+=("$x");; *) A+=("$x^{}");; esac; done; separa las opciones (-something) y argumentos (todo lo demás). Las opciones están en la matriz O mientras que los argumentos están en la matriz A. Tenga en cuenta que todos los argumentos tienen el ^{} adjunto, también, que salta sobre las anotaciones (de manera que puede usar etiquetas anotadas).

  • g(){ git show "${A[$1]}" && return; echo FAIL ${A[$1]}; git show "${A[$2]}"; }; crea una función de ayuda, que hace git show para el primer argumento. Si eso falla, emite "FAIL first-argument" y luego emite el segundo argumento. Este es un truco para reducir la sobrecarga en caso de que algo falle. (A managment de error adecuado sería demasiado.)

  • diff "${O[@]}" <(g 0 1) <(g 1 0) carreras diff con las opciones dadas contra el primer argumento y el segundo argumento (con dicha FALLO error de repliegue al otro argumento para reducir el diff).

  • -- permite pasar diff -opciones (-something) a este alias/script.

Errores:

  • Número de argumentos no está marcada. Todo lo que está detrás del segundo argumento se ignora, y si le da muy pocos, simplemente ve FAIL o nada en absoluto.

  • Los errores son un poco extraños y complican la salida. Si no le gusta esto, ejecútelo con 2>/dev/null (o cambie la secuencia de comandos de manera apropiada).

  • No devuelve un error si se rompe algo.

  • Es probable que desee alimentar esto en un buscapersonas de forma predeterminada.

Tenga en cuenta que es fácil de definir algunos más alias como:

git config --global alias.udiff '!git sdiff -u' 
git config --global alias.bdiff '!git sdiff -b' 

git config --global alias.pager '!pager() { cd "$GIT_PREFIX" && git -c color.status=always -c color.ui=always "[email protected]" 2>&1 | less -XFR; }; pager' 
git config --global alias.ddiff '!git pager udiff' 

espero que esto no es necesario que se explicará más adelante.

Para más alias por el estilo, tal vez echar un vistazo a my GitHub repo

Cuestiones relacionadas