¿Cómo puedo obtener una diferencia de lado a lado cuando hago "git diff"?

163

Cuando escribo "git diff", me gustaría ver un diff de lado a lado, como con "diff -y", o me gustaría mostrar el diff en una herramienta de diferencias interactiva como "kdiff3". ¿Cómo se puede hacer esto?

Miguel
fuente

Respuestas:

89

Aunque Git tiene una implementación interna de diff, puede configurar una herramienta externa en su lugar.

Hay dos formas diferentes de especificar una herramienta de diferencia externa:

  1. el establecimiento de las GIT_EXTERNAL_DIFFy los GIT_DIFF_OPTSvariables de entorno.
  2. configurar la herramienta diff externa a través de git config

Ver también:

Al hacer un git diff, Git verifica tanto la configuración de las variables de entorno anteriores como su .gitconfigarchivo.

Por defecto, Git pasa los siguientes siete argumentos al programa diff:

path  old-file  old-hex old-mode  new-file  new-hex new-mode

Por lo general, solo necesita los parámetros de archivo antiguo y archivo nuevo. Por supuesto, la mayoría de las herramientas diff solo toman dos nombres de archivo como argumento. Esto significa que debe escribir una pequeña secuencia de comandos de envoltura, que toma los argumentos que Git proporciona a la secuencia de comandos y los entrega al programa externo de git que elija.

Digamos que pones tu wrapper-script debajo ~/scripts/my_diff.sh:

#!/bin/bash
# un-comment one diff tool you'd like to use

# side-by-side diff with custom options:
# /usr/bin/sdiff -w200 -l "$2" "$5" 

# using kdiff3 as the side-by-side diff:
# /usr/bin/kdiff3 "$2" "$5"

# using Meld 
/usr/bin/meld "$2" "$5"

# using VIM
# /usr/bin/vim -d "$2" "$5"

entonces necesita hacer que ese script sea ejecutable:

chmod a+x ~/scripts/my_diff.sh

luego debe decirle a Git cómo y dónde encontrar su script de envoltorio de diferencias personalizado. Tiene tres opciones para hacerlo: (prefiero editar el archivo .gitconfig)

  1. Utilizando GIT_EXTERNAL_DIFF,GIT_DIFF_OPTS

    por ejemplo, en su archivo .bashrc o .bash_profile puede establecer:

    GIT_EXTERNAL_DIFF=$HOME/scripts/my_diff.sh
    export GIT_EXTERNAL_DIFF
    
  2. Utilizando git config

    use "git config" para definir dónde se puede encontrar su script de envoltura:

    git config --global diff.external ~/scripts/my_diff.sh
    
  3. Editando tu ~/.gitconfigarchivo

    puedes editar tu ~/.gitconfigarchivo para agregar estas líneas:

    [diff]
      external = ~/scripts/my_diff.sh
    

Nota:

De manera similar a la instalación de su herramienta de diferencias personalizada, también puede instalar una herramienta de fusión personalizada, que podría ser una herramienta de fusión visual para ayudar a visualizar mejor la fusión. (ver la página progit.org)

Ver: http://fredpalma.com/518/visual-diff-and-merge-tool/ y https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration

Tilo
fuente
1
¿Esto retiene la coloración terminal git?
Sridhar Sarnobat
3
Esto es genial, pero lanza un nuevo visor para cada archivo. ¿Alguna forma de crear un diff consolidado en, digamos meld,?
HRJ
2
@Tilo Recibo un error para vim como im: Advertencia: la salida no es a un terminal
programador muerto
¿Se meldpuede configurar la versión para hacer un directorio diff, donde puedo elegir para qué archivo (s) quiero ver el diff? Actualmente ejecuta un meldcomando separado para cada archivo, y tengo que salir meldpara ver el siguiente archivo. Prefiero meldmostrarme una lista de directorio de archivos modificados como se comporta cuando meldse usa desde Mercurial.
kasperd
163

Prueba git difftool

Usar en git difftoollugar de git diff. Nunca volverás

ACTUALIZAR para agregar un ejemplo de uso:

Aquí hay un enlace a otro stackoverflow que habla sobre git difftool: ¿Cómo veo la salida 'git diff' con mi herramienta / visor diff preferido?

Para las versiones más recientes de git, el difftoolcomando admite muchas herramientas externas externas listas para usar. Por ejemplo, vimdiffse admite automáticamente y se puede abrir desde la línea de comandos:

cd /path/to/git/repo
git difftool --tool=vimdiff

Otras herramientas externas de soporte compatibles se enumeran a través de git difftool --tool-helpaquí es un ejemplo de salida:

'git difftool --tool=<tool>' may be set to one of the following:
        araxis
        kompare
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        bc3
        codecompare
        deltawalker
        diffuse
        ecmerge
        emerge
        gvimdiff
        gvimdiff2
        kdiff3
        meld
        opendiff
        tkdiff
        xxdiff
Matt Ball
fuente
34
O tal vez volverás si lo consigues This message is displayed because 'diff.tool' is not configured.. Tal vez actualice la respuesta con un mínimo de cómo configurar esta cosa, para que muestre diferencias lado a lado en el terminal, ¿qué es lo que solicitó OP? Las herramientas GUI son bastante inútiles en el servidor remoto donde te conectas usando ssh.
Petr
1
Punto interesante, aunque no creo que personalmente haya necesitado usar git mientras SSH'd. Una de las cosas buenas de DVCS es la parte distribuida: al menos en mis entornos, nunca es una molestia clonar localmente cualquier repositorio que quiera buscar.
Matt Ball
1
Al menos en mi configuración, git difftoolcon vimdiffno siempre se alinean los dos archivos / buffers correctamente.
Rohmer
1
Eso es bueno, y así abajo en la lista de respuestas: git difftool -yO uso para evitar el aviso
tkdiff
Relacionado: haga que su fusión git difftoolen Windows y Linux: stackoverflow.com/a/48979939/4561887
Gabriel Staples el
55

También puedes intentarlo git diff --word-diff. No es exactamente uno al lado del otro, pero de alguna manera es mejor, por lo que podría preferirlo a su necesidad real de lado a lado.

mb14
fuente
12
Esta es la manera más fácil. Lo que es aún mejor esgit diff --word-diff=color
Rolf
@Rolf --word-diff=colorme da un error de opción no válida. ¿En qué versión se introdujo?
Holloway
@Trengot ejecuto git 1.7.9 que es del 02/2012
Rolf
44
La versión instalada predeterminada de @Rolf aquí es 1.7.1. Podría explicar la diferencia. git diff --color-wordsfunciona.
Holloway
44
Sí, git diff --color-wordses el camino a seguir en las versiones modernas de git.
VasiliNovikov
41

ydiff

Anteriormente llamada cdiff, esta herramienta puede mostrar diferencias de lado a lado , incrementales y coloridas .

En lugar de hacer git diff, haz:

ydiff -s -w0

Esto se iniciará ydiffen modo de visualización de lado a lado para cada uno de los archivos con diferencias.

Instalar con:

python3 -m pip install --user ydiff

-o-

brew install ydiff

Para git log, puedes usar:

ydiff -ls -w0

-w0detecta automáticamente el ancho de su terminal. Consulte la ydiff página del repositorio de GitHub para obtener detalles y una demostración.

Probado en Git 2.18.0, ydiff 1.1.

ymattw
fuente
@RyneEverett: ¿Puedes explicar cómo hacer el equivalente de git diff | cdiff -scon icdiff?
einpoklum
Sólo tiene que ejecutar ydiff -sdesde un git / SVN / hg espacio de trabajo, usted no tiene que canalizar en.
ymattw
si desea limitar la diferencia a un archivo específico a través del historial de Git, cd <git repo>y luego ejecutarydiff -ls <path/to/file>
slm
22

Puede hacer una en paralelo diffusando sdifflo siguiente:

$ git difftool -y -x sdiff  HEAD^ | less

donde HEAD^es un ejemplo que debe reemplazar con lo que quiera diferir.

Encontré esta solución aquí, donde también hay otras sugerencias. Sin embargo, esta respuesta es la pregunta del OP de manera sucinta y clara.

Ver man git-difftool para una explicación de los argumentos.


Teniendo en cuenta los comentarios, puede crear un git sdiffcomando útil escribiendo el siguiente script ejecutable:

#!/bin/sh
git difftool -y -x "sdiff -w $(tput cols)" "${@}" | less

Guardarlo como /usr/bin/git-sdiffy chmod -xél. Entonces podrás hacer esto:

$ git sdiff HEAD^
starfry
fuente
Usualmente hago "$ git difftool -x 'sdiff -s -w 240'" (o el ancho de pantalla que sea) si / cuando quiero suprimir las mismas líneas y solo hay un archivo (si no lo hago, vimdiff)
HidekiAI
1
@HidekiAI Me parece que es un dolor para escribir el terminal en anchura cada vez, así que utilizo tput colsen lugar, por ejemplo: git difftool -x "sdiff -s -w $(tput cols)".
jaume
¿Puede resaltar los cambios de color? En este momento parece que tenemos que usar nuestros ojos para detectar cuáles son realmente los cambios
polaridad
Sustituya sdiff por icdiff para obtener una bonita pantalla a color.
Greg
10
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

entonces simplemente:

git diff
krzych
fuente
1
"fusión" funciona tambien! Y muestra todos los cambios en una ventana consolidada.
HRJ
@HRJ que funciona perfectamente! Tan simple y práctico :)
waldyrious
9

Si desea ver diferencias de lado a lado en un navegador sin involucrar a GitHub, puede disfrutar de git webdiff , un reemplazo directo para git diff:

$ pip install webdiff
$ git webdiff

Esto ofrece una serie de ventajas sobre las herramientas de interfaz gráfica de usuario tradicionales, ya tkdiffque puede darle resaltado de sintaxis y mostrar diferencias de imagen.

Lea más sobre esto aquí .

danvk
fuente
7

Yo uso colordiff .

En Mac OS X, instálelo con

$ sudo port install colordiff

En Linux es posible apt get install colordiffo algo así, dependiendo de su distribución.

Luego:

$ git difftool --extcmd="colordiff -ydw" HEAD^ HEAD

O crea un alias

$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""

Entonces puedes usarlo

$ git diffy HEAD^ HEAD

Lo llamé "diffy" porque diff -yes la diferencia de lado a lado en unix. Colordiff también agrega colores, que son más agradables. En la opción -ydw, yes para el lado a lado, wes para ignorar los espacios en blanco, y des para producir el mínimo diff (generalmente obtienes un mejor resultado como diff)

Luigi R. Viggiano
fuente
agregar -ypara omitir la Launch 'colordiff' [Y/n]:solicitud.
Beni Cherniavsky-Paskin
estas seguro que es git alias diffy "difftool --extcmd=\"colordiff -ydw\""? ¿No debería ser git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\""?
polaridad
6

Para unix, combinando solo gity el incorporado diff:

git show HEAD:path/to/file | diff -y - path/to/file

Por supuesto, puede reemplazar HEAD con cualquier otra referencia de git, y probablemente desee agregar algo como -W 170al comando diff.

Esto supone que solo está comparando el contenido de su directorio con una confirmación anterior. La comparación entre dos confirmaciones es más compleja. Si su shell es bashpuede usar "sustitución de proceso":

diff -y -W 170 <(git show REF1:path/to/file) <(git show REF2:path/to/file)

donde REF1y REF2son referencias de git: etiquetas, ramas o hashes.

Walker Hale IV
fuente
Gracias: su comando 'git show HEAD: ruta / a / archivo' era lo que necesitaba para encontrar mi propia solución, 'vimdfiff <(git show HEAD: ruta / a / archivo) ruta / a / archivo'. Los bits todavía no están alineados correctamente, pero esa es la mejor solución que tengo en este momento.
talexb
5

¡Personalmente me gusta mucho icdiff !

Si estás en Mac OS Xla HomeBrew, acaba de hacer brew install icdiff.

Para obtener las etiquetas de archivo correctamente, además de otras características interesantes, tengo en mi ~/.gitconfig:

[pager]
    difftool = true
[diff]
    tool = icdiff
[difftool "icdiff"]
    cmd = icdiff --head=5000 --highlight --line-numbers -L \"$BASE\" -L \"$REMOTE\" \"$LOCAL\" \"$REMOTE\"

Y lo uso como: git difftool

Jose Alban
fuente
3

Esta pregunta apareció cuando estaba buscando una forma rápida de usar la forma integrada de git para localizar diferencias. Mi criterio de solución:

  • Inicio rápido, opciones integradas necesarias
  • Puede manejar muchos formatos fácilmente, xml, diferentes lenguajes de programación
  • Identifique rápidamente pequeños cambios de código en grandes archivos de texto

Encontré esta respuesta para obtener color en git.

Para obtener la diferencia de lado a lado en lugar de la diferencia de línea, modifiqué la excelente respuesta de mb14 a esta pregunta con los siguientes parámetros:

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]"

Si no le gusta el extra [- o {+, --word-diff=colorpuede usar la opción .

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]" --word-diff=color

Eso ayudó a obtener una comparación adecuada tanto con el texto json y xml como con el código java.

En resumen, las --word-diff-regexopciones tienen una visibilidad útil junto con la configuración de color para obtener una experiencia de código fuente de color lado a lado en comparación con la diferencia de línea estándar, al navegar a través de archivos grandes con pequeños cambios de línea.

Miguel
fuente
3

Varios otros ya mencionaron cdiff para la diferenciación de git de lado a lado, pero nadie dio una implementación completa.

Configurar cdiff:

git clone https://github.com/ymattw/cdiff.git
cd cdiff
ln -s `pwd`/cdiff ~/bin/cdiff
hash -r # refresh your PATH executable in bash (or 'rehash' if you use tcsh)
        # or just create a new terminal

Edite ~ / .gitconfig insertando estas líneas:

[pager]
        diff = false
        show = false

[diff]
        tool = cdiff
        external = "cdiff -s $2 $5 #"

[difftool "cdiff"]
        cmd = cdiff -s \"$LOCAL\" \"$REMOTE\"

[alias]
        showw = show --ext-dif

El buscapersonas es necesario para que cdiff funcione con Diff, de todos modos es esencialmente un buscapersonas, por lo que está bien. Difftool funcionará independientemente de esta configuración.

El alias show es necesario porque git show solo admite herramientas diff externas a través de argumentos.

El '#' al final del comando externo diff es importante. El comando diff de Git agrega un $ @ (todas las variables diff disponibles) al comando diff, pero solo queremos los dos nombres de archivo. Entonces llamamos a esos dos explícitamente con $ 2 y $ 5, y luego ocultamos los $ @ detrás de un comentario que de lo contrario confundiría a sdiff. Resultando en un error que se parece a:

fatal: <FILENAME>: no such path in the working tree
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

Comandos Git que ahora producen una diferencia de lado a lado:

git diff <SHA1> <SHA2> 
git difftool <SHA1> <SHA2>
git showw <SHA>

Uso de cdiff:

'SPACEBAR' - Advances the page of the current file.
'Q'        - Quits current file, thus advancing you to the next file.

Ahora tiene diff de lado a lado a través de git diff y difftool. Y tiene el código fuente de cdiff python para la personalización del usuario avanzado si lo necesita.

Eric
fuente
2

Aquí hay un enfoque. Si pasa menos, el ancho xterm se establece en 80, que no es tan caliente. Pero si continúa con el comando, por ejemplo, COLS = 210, puede utilizar su xterm expandido.

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}
Thomas Mellman
fuente
1
Gracioso. Firmé por mi nombre con un seudónimo, pero eso fue ignorado ... Gracias por revelarme, Stack Overflow. :(
Thomas Mellman
2

Abra Intellij IDEA , seleccione una o varias confirmaciones en la ventana de la herramienta "Control de versiones", explore los archivos modificados y haga doble clic en ellos para inspeccionar los cambios uno al lado del otro para cada archivo.

Con el lanzador de línea de comandos incluido, puede traer IDEA a cualquier lugar con un simple idea some/path

vista de control de versiones vista diferencial

Holger Brandl
fuente
1

Hay muchas buenas respuestas en este hilo. Mi solución para este problema fue escribir un script.

Nombre este 'git-scriptname' (y hágalo ejecutable y póngalo en su RUTA, como cualquier script), y puede invocarlo como un comando git normal ejecutando

$ git scriptname

La funcionalidad real es solo la última línea. Aquí está la fuente:

#!/usr/bin/env zsh
#
#   Show a side-by-side diff of a particular file how it currently exists between:
#       * the file system
#       * in HEAD (latest committed changes)

function usage() {
    cat <<-HERE
    USAGE

    $(basename $1) <file>

    Show a side-by-side diff of a particular file between the current versions:

        * on the file system (latest edited changes)
        * in HEAD (latest committed changes)

HERE
}

if [[ $# = 0 ]]; then
    usage $0
    exit
fi

file=$1
diff -y =(git show HEAD:$file) $file | pygmentize -g | less -R
Jon Carter
fuente
1

Esta puede ser una solución algo limitada, pero hace el trabajo usando el diffcomando del sistema sin herramientas externas:

diff -y  <(git show from-rev:the/file/path) <(git show to-rev:the/file/path)
  • filtre solo el uso de las líneas de cambio --suppress-common-lines(si diffadmite la opción).
  • sin colores en este caso, solo los diffmarcadores habituales
  • puede ajustar el ancho de la columna --width=term-width; en Bash puede obtener el ancho como $COLUMNSo tput cols.

Esto también se puede incluir en un script de ayuda git para mayor comodidad, por ejemplo, para un uso como este:

git diffy the/file/path --from rev1 --to rev2
nomadbyte
fuente