¿Cómo puedo visualizar las diferencias por carácter en un archivo diff unificado?

122

Digamos que obtengo un parche creado con git format-patch. El archivo es básicamente un diff unificado con algunos metadatos. Si abro el archivo en Vim, puedo ver qué líneas se han modificado, pero no puedo ver qué caracteres difieren en las líneas cambiadas. ¿Alguien sabe una manera (en Vim, o algún otro software gratuito que se ejecuta en Ubuntu) para visualizar las diferencias por carácter?

Un ejemplo de contador donde se visualiza la diferencia por carácter es cuando se ejecuta vimdiff a b.

actualizar vie 12 nov 22:36:23 UTC 2010

diffpatch es útil para el escenario en el que está trabajando con un solo archivo.

actualizar jue 16 jun 17:56:10 UTC 2016

Echa un vistazo a diff-highlight en git 2.9 . Este script hace exactamente lo que estaba buscando originalmente.

Adam Monsen
fuente
Esto podría ser mejor en
superuser.com
13
Quizás. Elegí stackoverflow.com porque las preguntas frecuentes mencionan que este es el lugar para preguntas sobre "herramientas de software comúnmente utilizadas por programadores"
Adam Monsen
77
No estoy seguro de que esto responda directamente a su pregunta, pero git diff --color-wordses muy útil para ver qué palabras tienen cambios dentro de las líneas, en lugar de la salida unificada habitual. Sin embargo, está basado en palabras en lugar de en caracteres, por lo que si no hay mucho espacio en blanco en el contenido que está diferenciando, la salida puede ser menos ordenada. (Editado: Vaya, veo que entendí mal lo que estás pidiendo, sin embargo, tal vez este comentario sería útil para alguien.)
Mark Longair

Respuestas:

13

Dadas sus referencias a Vim en la pregunta, no estoy seguro de si esta es la respuesta que desea :) pero Emacs puede hacerlo. Abra el archivo que contiene el diff, asegúrese de que usted está en diff-mode(si el archivo se llama foo.diffo foo.patchesto se produce automáticamente, de lo contrario escriba M-x diff-mode RET), ir al trozo que le interesa y golpear C-c C-ba refine-hunk. O recorra el archivo un trozo a la vez con M-n; eso hará el refinamiento automáticamente.

legoscia
fuente
1
¡Funciona para mi! Heh, he usado Vim durante 10 años, pero acabo de instalar emacs. :)
Adam Monsen
Pero emacs no es compatible con la lectura de la entrada estándar, que no puedo hacer por ejemplogit log master.. -p | emacs -
Hi-Ángel
1
@ Hi-Angel Puede abrir Emacs y escribir M-!para ejecutar el comando y capturar la salida en un búfer.
legoscia
172

En git, puedes fusionarte sin comprometerte. Combine su parche primero, luego haga:

git diff --word-diff-regex=.

Tenga en cuenta el punto después del signo igual.

yingted
fuente
139
Mejor: git diff --color-words=..
ntc2
44
@ ntc2 Debería responder su comentario.
Tyler Collier
1
Los que votaron por favor, tengan en cuenta que mi caso de uso original supone que solo tiene un archivo de parche , sin repositorio git o incluso versiones base / modificadas. Es por eso que acepté la respuesta de @legoscia ... describe exactamente lo que se solicitó.
Adam Monsen
2
@ ntc2 git diff --color-words=.y git diff --color-words .funciona de manera diferente. Es mejor git diff --color-words ..
abhisekp
2
@abhisekp: gracias por la foto. Creo que lo descubrí: ¡ git diff --color-words .es realmente lo mismo que git diff --color-words -- .! Es decir, el .se interpreta como un camino. Puedes verificar con mkdir x y; echo foo > x/test; git add x/test; git commit -m test; echo boo > x/test; cd y; git diff --color-words=.; git diff --color-words .; git diff --color-words -- ..
ntc2
145

Aquí están algunas versiones con salida de menos ruidoso que git diff --word-diff-regex=<re>y que requieren menos de tipificación, pero son equivalentes a, git diff --color-words --word-diff-regex=<re>.

Simple (resalta los cambios de espacio):

git diff --color-words

Simple (resalta los cambios de caracteres individuales; no resalta los cambios de espacio):

git diff --color-words=.

Más complejo (resalta los cambios de espacio):

git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'

En general:

git diff --color-words=<re>

donde <re>es una expresión regular que define "palabras" con el propósito de identificar cambios.

Estos son menos ruidosos en el sentido de que colorean las "palabras" cambiadas, mientras que el uso de solo --word-diff-regex=<re>"palabras" combina con -/+marcadores de colores .

ntc2
fuente
9
Yo mismo me gusta --color-words, sin la =.parte.
Tyler Collier
1
git diff --color-words='\w'funcionaría mejor con diacríticos (git v1.7.10.4)
nr
1
Su versión más compleja funciona muy bien. I anexa --word-diff=plaina tener adicionalmente [-y -]deleciones de sonido envolvente y {+y +}adiciones de sonido envolvente. Sin embargo, como advierte el manual, las ocurrencias reales de estos delimitadores en la fuente no se escapan de ninguna manera
Tobias Kienzler
2
Desafortunadamente, su versión más compleja no parece resaltar, por ejemplo, los cambios de sangría, he abierto una pregunta sobre esto
Tobias Kienzler
¡Esta respuesta es genial! Sin embargo, ¿hay alguna manera de cambiar realmente el fondo de esos cambios a verde / rojo?
WoLfPwNeR
45
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"

La expresión regular anterior ( de Thomas Rast ) hace un trabajo decente al separar fragmentos de diferencias en el nivel de puntuación / carácter (sin ser tan ruidoso como --word-diff-regex=.).

Publiqué una captura de pantalla de la salida resultante aquí .


Actualizar:

Este artículo tiene algunas sugerencias geniales. Específicamente, el contrib/árbol del repositorio de git tiene una diff-highlightsecuencia de comandos perl que muestra resaltados finos.

Inicio rápido para usarlo:

$ curl https://git.kernel.org/cgit/git/git.git/plain/contrib/diff-highlight/diff-highlight > diff-highlight
$ chmod u+x diff-highlight
$ git diff --color=always HEAD~10 | diff-highlight | less -R
Justin M. Keyes
fuente
55
Puede acortarlo a--color-words=[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Eddified
Tuve que agregar 'al principio del valor allí. De lo contrario, recibí un error. Además, simplemente usando --color-wordsobtengo exactamente el mismo comportamiento que usar esa expresión regular.
gcb
3
@gcb El contenido del texto es importante. Si sus cambios están separados por espacios en blanco, no hay diferencia. Pero si cambia si cambia algo parecido foo.bara foo.quxusted verá la diferencia.
Justin M. Keyes
55
Más simple: git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'.
ntc2
1
Había instalado git con Homebrew y ya tenía ese script en /usr/local/share/git-core/contrib/diff-highlight/diff-highlight. Esto parece sugerir que el git de Homebrew instala toda la contribución en /usr/local/share/git-core/contrib/. Finalmente, lo siguiente funcionó para mígit diff --color=always | /usr/local/share/git-core/contrib/diff-highlight/diff-highlight
Ashutosh Jindal
6

Si no tiene nada contra la instalación de NodeJS, hay un paquete llamado "diff-so-fancy" ( https://github.com/so-fancy/diff-so-fancy ), que es muy fácil de instalar y funciona perfectamente:

npm install -g diff-so-fancy
git diff --color | diff-so-fancy | less -R

Editar: Me acabo de enterar de que en realidad es un contenedor para el diferencial de resaltado oficial ... Al menos es más fácil de instalar para perlophobes como yo y la página de GitHub está bien documentada :)

walnutz
fuente
2

No conozco la herramienta de diferencia por carácter, pero hay una herramienta de diferencia por palabra: wdiff.

consulte ejemplos Las 4 herramientas de diferencia de archivos principales en UNIX / Linux: Diff, Colordiff, Wdiff, Vimdiff .

el friki
fuente
wdiff es interesante, gracias! Para aclarar mi pregunta original, estoy buscando algo que proporcione un resaltado de sintaxis mejorado para un solo archivo que esté en formato diff unificado.
Adam Monsen
Ligeramente atópico (sobre diferencias palabra por palabra, sin mejorar una salida diferencial preexistente), pero he encontrado las siguientes combinaciones mejores para visualizaciones palabra por palabra: * wdiff old_file new_file | cdiff * vimdiff , luego dentro de vim :windo wincmd Kpara cambiar al diseño de ventana vertical (uno debajo del otro) uno al lado del otro. Ese diseño es mucho mejor para archivos con líneas largas.
Aleksander Adamowski
2
Por cierto, algunas otras herramientas vale la pena ver, no se menciona en el artículo enlazado: wdiff2, mdiffy la herramienta en línea de Google .
Aleksander Adamowski
1

Después de un poco de investigación, noté que esta pregunta apareció dos veces recientemente en la lista de correo principal de Vim. El complemento NrrwRgn se mencionó en ambas ocasiones (haga dos regiones estrechas y difúndalas). Usar NrrwRgn como lo describe Christian Brabandt se siente más como una solución que como una solución, pero tal vez eso sea lo suficientemente bueno.

Probé NrrwRgn y, junto con: diffthis, fue realmente útil para ilustrar las diferencias por carácter dentro de partes de un solo archivo. Pero tomó muchas teclas. Mi Vimscript está bastante oxidado, pero probablemente podría tener un script. Tal vez NrrwRgn podría mejorarse para proporcionar la funcionalidad deseada.

Pensamientos?

Adam Monsen
fuente