¿Cómo veo la salida ‘git diff’ con mi herramienta / visor de diferencias preferido?

Cuando git diff , quiero ver el resultado con mi herramienta visual diff de elección (SourceGear “diffmerge” en Windows). ¿Cómo configuro git para hacer esto?

Desde Git1.6.3, puede usar el script git difftool : vea mi respuesta a continuación .


Puede ser que este artículo te ayude. Estas son las mejores partes:

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

El primero es el método que usaste, configurando la variable GIT_EXTERNAL_DIFF. Sin embargo, se supone que la variable apunta a la ruta completa del ejecutable. Además, el ejecutable especificado por GIT_EXTERNAL_DIFF se invocará con un conjunto fijo de 7 argumentos:

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

Como la mayoría de las herramientas de diferencias requerirán un orden diferente (y solo algunos) de los argumentos, lo más probable es que tengas que especificar un script de envoltura, que a su vez llama a la herramienta de diferencia real.

El segundo método, que prefiero, es configurar la herramienta externa diff a través de “git config” . Aquí esta lo que hice:

1) Cree un script de envoltura “git-diff-wrapper.sh” que contenga algo así como

 -->8-(snip)-- #!/bin/sh # diff is called by git with 7 parameters: # path old-file old-hex old-mode new-file new-hex new-mode "" "$2" "$5" | cat --8<-(snap)-- 

Como puede ver, solo el segundo ("archivo antiguo") y el quinto ("nuevo archivo") se pasarán a la herramienta diff.

2) Tipo

 $ git config --global diff.external  

en el símbolo del sistema, reemplazando con la ruta a "git-diff-wrapper.sh", por lo que su ~ / .gitconfig contiene

 -->8-(snip)-- [diff] external =  --8<-(snap)-- 

Asegúrese de usar la syntax correcta para especificar las rutas de acceso a la herramienta script y diff del wrapper, es decir, use slashed directo en lugar de barras diagonales inversas. En mi caso, tengo

 [diff] external = \"c:/Documents and Settings/sschuber/git-diff-wrapper.sh\" 

en .gitconfig y

 "d:/Program Files/Beyond Compare 3/BCompare.exe" "$2" "$5" | cat 

en la secuencia de comandos envoltura. ¡Cuidado con el "gato" final!

(Supongo que el ' | cat ' es necesario solo para algunos progtwigs que pueden no devolver un estado de devolución correcto o consistente. Es posible que desee probar sin el gato final si su herramienta diff tiene un estado de devolución explícito)


Eso (el artículo citado anteriormente) es la teoría para la herramienta externa definida a través del archivo de configuración (no a través de la variable de entorno).
En la práctica (aún para la definición del archivo de configuración de la herramienta externa), puede consultar:

  • ¿Cómo configuro DiffMerge con msysgit / gitk? que ilustra la configuración concreta de DiffMerge y WinMerge para MsysGit y gitk
  • ¿Cómo puedo configurar un editor para trabajar con Git en Windows? para la definición de Notepad ++ como editor externo.

Para completar mi respuesta de configuración anterior “diff.external” más arriba:

Como menciona Jakub , Git1.6.3 introdujo git difftool , originalmente propuesto en septiembre de 2008:

USAGE = '[--tool=tool] [--commit=ref] [--start=ref --end=ref] [--no-prompt] [file to merge]'
(Ver --extcmd en la última parte de esta respuesta)

$LOCAL contiene el contenido del archivo de la revisión inicial y $REMOTE contiene el contenido del archivo en la revisión final.
$BASE contiene el contenido del archivo en el wor

Básicamente es git-mergetool modificado para operar en el índice git / worktree.

El caso de uso habitual para esta secuencia de comandos es cuando tiene cambios escalonados o no escalonados y le gustaría ver los cambios en un visor de diff lado a lado (por ejemplo, tkdiff , tkdiff , etc.).

 git difftool [*] 

Otro caso de uso es cuando le gustaría ver la misma información, pero está comparando las confirmaciones arbitrarias (esta es la parte donde el análisis revarg podría ser mejor)

 git difftool --start=HEAD^ --end=HEAD [-- *] 

El último caso de uso es cuando desea comparar su árbol de trabajo actual con algo que no sea HEAD (por ejemplo, una etiqueta)

 git difftool --commit=v1.0.0 [-- *] 

Nota: ¡desde Git 2.5, git config diff.tool winmerge es suficiente!
Ver ” git mergetool winmerge ”

Y desde Git 1.7.11 , tiene la opción --dir-diff , para generar herramientas de diferencias externas que pueden comparar dos jerarquías de directorios a la vez después de llenar dos directorios temporales, en lugar de ejecutar una instancia de la herramienta externa una vez por un par de archivos.


Antes de Git 2.5:

Caso práctico para configurar difftool con su herramienta personalizada diff:

 C:\myGitRepo>git config --global diff.tool winmerge C:\myGitRepo>git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\"" C:\myGitRepo>git config --global difftool.prompt false 

Con winmerge.sh almacenado en una parte del directorio de tu RUTA:

 #!/bin/sh echo Launching WinMergeU.exe: $1 $2 "C:/Program Files/WinMerge/WinMergeU.exe" -u -e "$1" "$2" -dl "Local" -dr "Remote" 

Si tiene otra herramienta (kdiff3, P4Diff, …), cree otra secuencia de comandos de shell y la correspondiente directiva difftool.myDiffTool.cmd config.
Luego puede cambiar fácilmente las herramientas con la configuración diff.tool .

También tiene esta entrada de blog de Dave para agregar otros detalles.
(O esta pregunta para las opciones de winmergeu )

El interés con esta configuración es el script winmerge.sh : puede personalizarlo para tener en cuenta casos especiales.

Véase, por ejemplo, la respuesta de David Marble a continuación para un ejemplo que trata de:

  • nuevos archivos en origen o destino
  • archivos eliminados en origen o destino

Como Kem Mason menciona en su respuesta , también puedes evitar cualquier envoltorio usando la opción --extcmd :

 --extcmd= 

Especifique un comando personalizado para ver diffs. git-difftool ignora los valores predeterminados configurados y ejecuta $command $LOCAL $REMOTE cuando se especifica esta opción.

Por ejemplo, así es como gitk puede ejecutar / usar cualquier herramienta diff .

En el espíritu de responder preguntas que son algo diferentes a las preguntas. Prueba esta solución:

 $ meld my_project_using_git 

Meld entiende git y proporciona navegación alrededor de los cambios recientes.

Desde la versión 1.6.3 de git, hay ” git difftool ” que puedes configurar para usar tu herramienta favorita de diferencias gráficas. Actualmente compatibles con out-of-the-box son kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, diffuse y opendiff ; si la herramienta que desea utilizar no está en esta lista, siempre puede usar la opción de configuración ‘ difftool..cmd ‘.

“git difftool” acepta las mismas opciones que “git diff”.

Con el nuevo git difftool , es tan simple como agregar esto a su archivo .gitconfig :

 [diff] tool = any-name [difftool "any-name"] cmd = "\"C:/path/to/my/ext/diff.exe\" \"$LOCAL\" \"$REMOTE\"" 

También mire hacia fuera el error , un script simple que escribí para extender el molesto comportamiento de diferencia (IMO) de abrir cada uno en serie.

Tengo una adición a esto. Me gusta utilizar regularmente una aplicación diff que no es compatible como una de las herramientas predeterminadas (por ejemplo, caleidoscopio), a través de

 git difftool -t 

También me gusta que la diff predeterminada sea la línea de comando normal, por lo que establecer la variable GIT_EXTERNAL_DIFF no es una opción.

Puede utilizar una aplicación arbitraria diff como una aplicación única con este comando:

 git difftool --extcmd=/usr/bin/ksdiff 

Simplemente pasa los 2 archivos al comando que especifiques, por lo que probablemente tampoco necesites un contenedor.

Basándose en la respuesta de VonC para tratar con eliminaciones y adiciones de archivos, use los siguientes comandos y scripts:

 > git config --global diff.tool winmerge > git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\" \"$BASE\"" > git config --global difftool.prompt false 

Lo cual es lo mismo que poner esto en tu .gitconfig global:

 [diff] tool = winmerge [difftool "winmerge"] cmd = winmerge.bat "$LOCAL" "$REMOTE" "$BASE" [difftool] prompt = false 

A continuación, coloque lo siguiente en winmerge.sh que debe estar en su ruta:

 #!/bin/sh NULL="/dev/null" if [ "$2" = "$NULL" ] ; then echo "removed: $3" elif [ "$1" = "$NULL" ] ; then echo "added: $3" else echo "changed: $3" "C:/Program Files (x86)/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$1" "$2" fi 

Solución para Windows / msys git

Después de leer las respuestas, descubrí una manera más simple que implica cambiar solo un archivo.

  1. Cree un archivo por lotes para invocar su progtwig diff, con el argumento 2 y 5. Este archivo debe estar en algún lugar de su ruta. (Si no sabe dónde está eso, colóquelo en c: \ windows). Llámalo, por ejemplo, “gitdiff.bat”. El mio es:

     @echo off REM This is gitdiff.bat "C:\Program Files\WinMerge\WinMergeU.exe" %2 %5 
  2. Establezca la variable de entorno para que apunte a su archivo por lotes. Por ejemplo: GIT_EXTERNAL_DIFF=gitdiff.bat . O a través de powershell escribiendo git config --global diff.external gitdiff.bat .

    Es importante no utilizar comillas o especificar ninguna información de ruta; de lo contrario, no funcionará. Es por eso que gitdiff.bat debe estar en tu camino.

Ahora cuando escribe “git diff”, invocará su visor de diferencias externo.

Si estás haciendo esto a través de cygwin, es posible que necesites usar cygpath :

 $ git config difftool.bc3.cmd "git-diff-bcomp-wrapper.sh \$LOCAL \$REMOTE" $ cat git-diff-bcomp-wrapper.sh #!/bin/sh "c:/Program Files (x86)/Beyond Compare 3/BComp.exe" `cygpath -w $1` `cygpath -w $2` 

esto funciona para mí en Windows 7. No hay necesidad de scripts intermedios sh

contenidos de .gitconfig:

  [diff] tool = kdiff3 [difftool] prompt = false [difftool "kdiff3"] path = C:/Program Files (x86)/KDiff3/kdiff3.exe cmd = "$LOCAL" "$REMOTE" 

Un breve resumen de las excelentes respuestas anteriores:

 git difftool --tool-help git config --global diff.tool  git config --global --add difftool.prompt false 

Luego úsala escribiendo (opcionalmente especificando también el nombre del archivo):

 git difftool 

Introducción

Como referencia, me gustaría incluir mi variación en la respuesta de VonC. Tenga en cuenta que estoy usando la versión MSys de Git (1.6.0.2 en este momento) con PATH modificada, y ejecutando Git de Powershell (o cmd.exe), no el shell Bash.

Introduje un nuevo comando, gitdiff . Al ejecutar este comando, se redirige temporalmente a git diff para usar un progtwig de diferencia visual de su elección (a diferencia de la solución de VonC que lo hace permanentemente). Esto me permite tener tanto la funcionalidad de diferencia de Git por defecto ( git diff ) como la funcionalidad de diferencia visual ( gitdiff ). Ambos comandos toman los mismos parámetros, por lo que, para diferenciar visualmente los cambios en un archivo en particular, puede escribir

 gitdiff path/file.txt 

Preparar

Tenga en cuenta que $GitInstall se usa como marcador de posición para el directorio donde está instalado Git.

  1. Crea un nuevo archivo, $GitInstall\cmd\gitdiff.cmd

     @echo off setlocal for /F "delims=" %%I in ("%~dp0..") do @set path=%%~fI\bin;%%~fI\mingw\bin;%PATH% if "%HOME%"=="" @set HOME=%USERPROFILE% set GIT_EXTERNAL_DIFF=git-diff-visual.cmd set GIT_PAGER=cat git diff %* endlocal 
  2. Cree un nuevo archivo, $GitInstall\bin\git-diff-visual.cmd (reemplazando el marcador de posición [visual_diff_exe] con la ruta completa al progtwig diff de su elección)

     @echo off rem diff is called by git with 7 parameters: rem path old-file old-hex old-mode new-file new-hex new-mode echo Diffing "%5" "[visual_diff_exe]" "%2" "%5" exit 0 
  3. Ya has terminado. La ejecución de gitdiff desde un repository de Git ahora debería invocar su progtwig visual diff para cada archivo que se haya cambiado.

Aquí hay un archivo de proceso por lotes que funciona para Windows: asume que DiffMerge está instalado en la ubicación predeterminada, maneja x64, maneja la sustitución de barras diagonales hacia atrás según sea necesario y tiene la capacidad de instalarse. Debería ser fácil reemplazar DiffMerge con su progtwig favorito de diferencias.

Instalar:

 gitvdiff --install 

gitvdiff.bat:

 @echo off REM ---- Install? ---- REM To install, run gitvdiff --install if %1==--install goto install REM ---- Find DiffMerge ---- if DEFINED ProgramFiles^(x86^) ( Set DIFF="%ProgramFiles(x86)%\SourceGear\DiffMerge\DiffMerge.exe" ) else ( Set DIFF="%ProgramFiles%\SourceGear\DiffMerge\DiffMerge.exe" ) REM ---- Switch forward slashes to back slashes ---- set oldW=%2 set oldW=%oldW:/=\% set newW=%5 set newW=%newW:/=\% REM ---- Launch DiffMerge ---- %DIFF% /title1="Old Version" %oldW% /title2="New Version" %newW% goto :EOF REM ---- Install ---- :install set selfL=%~dpnx0 set selfL=%selfL:\=/% @echo on git config --global diff.external %selfL% @echo off :EOF 

Si estás en una Mac y tienes XCode, entonces tienes FileMerge instalado. El comando del terminal es abierto, por lo que puedes hacer git difftool -t opendiff

Para obtener una versión de Linux de cómo configurar una herramienta diff en las versiones de git anteriores a la 1.6.3 (1.6.3 se agregó difftool a git) este es un gran tutorial conciso,

en breve:

Paso 1: agrégalo a tu .gitconfig

 [diff] external = git_diff_wrapper [pager] diff = 

Paso 2: crea un archivo llamado git_diff_wrapper, ponlo en algún lugar de tu $ PATH

 #!/bin/sh vimdiff "$2" "$5" 

Instalar meld

  # apt-get install meld 

Luego elige eso como difftool

  $ git config --global diff.tool meld 

Si desea ejecutarlo en el tipo de consola:

  $ git difftool 

Si quiere usar el modo gráfico, escriba:

  $ git mergetool 

Y la salida sería:

  'git mergetool' will now attempt to use one of the following tools: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare emerge vimdiff Merging: www/css/style.css www/js/controllers.js Normal merge conflict for 'www/css/style.css': {local}: modified file {remote}: modified file Hit return to start merge resolution tool (meld): 

Tan solo presione enter para usar meld (predeterminado), esto abriría el modo gráfico, hará que la magia se guarde y presione eso para resolver la fusión. Eso es todo

En Mac OS X,

 git difftool -t diffuse 

hace el trabajo por mí en la carpeta git. Para la instalación difusa, uno puede usar el puerto –

 sudo port install diffuse 

puedes usar git difftool .

por ejemplo, si tiene meld , puede editar el branchs master y devel por:

 git config --global diff.external meld git difftool master..devel 

Después de mirar algunas otras herramientas de diferencias externas, encontré que la vista diff en IntelliJ IDEA (y Android Studio) es la mejor para mí.

Paso 1: configurar IntelliJ IDEA para que se ejecute desde la línea de comando

Si desea utilizar IntelliJ IDEA como su herramienta de diferenciación, primero debe configurar IntelliJ IDEA para que se ejecute desde la línea de comando siguiendo las instrucciones aquí :

En macOS o UNIX:

  1. Asegúrese de que IntelliJ IDEA se está ejecutando.
  2. En el menú principal, elija Tools | Create Command-line Launcher Tools | Create Command-line Launcher . Se abre el cuadro de diálogo Crear secuencia de comandos del iniciador, con la ruta sugerida y el nombre del script del iniciador. Puede aceptar valores predeterminados o especificar su propia ruta. Notifíquelo, ya que lo necesitará más tarde. Fuera de IntelliJ IDEA, agregue la ruta y el nombre del script de inicio a su ruta.

En Windows:

  1. Especifique la ubicación del ejecutable IntelliJ IDEA en la variable de entorno del sistema Path. En este caso, podrá invocar el ejecutable IntelliJ IDEA y otros comandos IntelliJ IDEA desde cualquier directorio.

Paso 2: configure git para usar IntelliJ IDEA como difftool

Siguiendo las instrucciones en esta publicación de blog :

Intento

 export INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS PATH=$IDEA_HOME $PATH 

Pescado

 set INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS set PATH $INTELLIJ_HOME $PATH 

Ahora agrega lo siguiente a tu configuración de git:

 [merge] tool = intellij [mergetool "intellij"] cmd = idea merge $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE") $(cd $(dirname "$BASE") && pwd)/$(basename "$BASE") $(cd $(dirname "$MERGED") && pwd)/$(basename "$MERGED") trustExitCode = true [diff] tool = intellij [difftool "intellij"] cmd = idea diff $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE") 

Puedes probarlo con git difftool o git difftool HEAD~1

Probé las cosas elegantes aquí (con tkdiff) y nada funcionó para mí. Entonces escribí el siguiente script, tkgitdiff. Hace lo que necesito que haga.

 $ cat tkgitdiff #!/bin/sh # # tkdiff for git. # Gives you the diff between HEAD and the current state of your file. # newfile=$1 git diff HEAD -- $newfile > /tmp/patch.dat cp $newfile /tmp savedPWD=$PWD cd /tmp patch -R $newfile < patch.dat cd $savedPWD tkdiff /tmp/$newfile $newfile 

He estado usando este bit en ~/.gitconfig durante mucho tiempo:

 [diff] external = ~/Dropbox/source/bash/git-meld 

Con git-meld :

 #!/bin/bash if [ "$DISPLAY" = "" ]; then diff $2 $5 else meld $2 $5 fi 

Pero ahora me cansé de usar siempre meld en el entorno gráfico, y no es trivial invocar el diff normal con esta configuración, así que cambié a esto:

 [alias] v = "!sh -c 'if [ $# -eq 0 ] ; then git difftool -y -t meld ; else git difftool -y $@ ; fi' -" 

Con esta configuración, cosas como esta funcionan:

 git v git v --staged git v -t kompare git v --staged -t tkdiff 

Y aún conservo el buen viejo git diff .

Yo uso kompare en ubuntu:

 sudo apt-get install kompare 

Para comparar dos twigs:

 git difftool -t kompare  master 

Si ya tiene una herramienta diff asociada con tipos de archivos (por ejemplo, porque instaló TortoiseSVN que viene con un visor de diferencias), puede canalizar la salida regular de git diff a un archivo “temp”, luego simplemente abra ese archivo directamente sin necesidad para saber algo sobre el espectador:

 git diff > "~/temp.diff" && start "~/temp.diff" 

Establecerlo como un alias global funciona aún mejor: git what

 [alias] what = "!f() { git diff > "~/temp.diff" && start "~/temp.diff"; }; f" 

Si no eres uno para la línea de comando, entonces si instalas tort git puedes hacer clic derecho sobre un archivo para obtener un submenú tortoisegit con la opción “Diff later”.

Cuando selecciona esto en el primer archivo, puede hacer clic derecho en el segundo archivo, ir al submenú tortoisegit y seleccionar “Dif. Con == su archivo aquí ==” Esto le dará a la guía de tortoisegitmerge el resultado.

Es posible que desee probar xd http://github.com/jiqingtang/xd , que es envoltorio GUI para diferencias GIT / SVN. NO es una herramienta diff en sí misma. Ejecuta xd cuando quiere ejecutar git diff o svn diff y le muestra una lista de archivos, una ventana de previsualización y puede ejecutar cualquier herramienta diff que le guste, incluyendo tkdiff, xxdiff, gvimdiff, emacs (ediff), xemacs ( ediff), meld, diffuse, kompare y kdiff3. También puede ejecutar cualquier herramienta personalizada.

Lamentablemente, la herramienta no es compatible con Windows.

Divulgación : soy el autor de esta herramienta.