use Winmerge dentro de Git para archivar diff

Respuestas:

113

Actualización de junio de 2015, 6 años después:

Como se detalla en " git mergetool winmerge ", un simple git config diff.tool winmergeserá suficiente.

¡Git 2.5+ (Q2, 2015) ahora conoce Winmerge como una herramienta de diferenciación o fusión!


Respuesta original (2009-2012)

(msysgit, 1.6.5, sesión de DOS)

La primera parte (usando winmerge) se describe en " ¿Cómo veo la salida 'git diff' con el programa visual diff? "

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

Con winmerge.shalmacenado en un directorio parte de su PATH:

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

(ver Opciones de la línea de comandos de WinMerge )

git difftool

ahora lanzará WinMerge.
Si desea git diffiniciar WinMerge, simplemente configure:

set GIT_EXTERNAL_DIFF=winmerge.sh

Pero el valor agregado real proviene de la capacidad de usar esa misma herramienta de diferencias para presentar todas las diferencias en un lote en lugar de presentarlas secuencialmente, lo que te obliga a cerrar las ventanas de la herramienta de diferencias de un archivo a la vez.

Actualización de junio de 2012 (2 años y medio después):

La comparación de directorios en lugar de archivo por archivo estará disponible pronto:
Vea [ANUNCIO] Git 1.7.11.rc1 :

" git difftool" aprendió la --dir-diffopción " " para generar herramientas de diferencias externas que pueden comparar dos jerarquías de directorios a la vez después de completar dos directorios temporales, en lugar de ejecutar una instancia de la herramienta externa una vez por par de archivos .

Consulte " Parche difftool: enseñar difftoola manejar diferencias de directorio " y la respuesta " Comparación de directorios de ramas de Git " para obtener más detalles.


Diftool original por el script de directorios (diciembre de 2009)

Como menciona Seba Illingworth en su respuesta , un script git-diffall.sh (también incluido en la ruta) puede hacer precisamente eso:

#!/bin/sh
git diff --name-only "$@" | while read filename; do
    git difftool "$@" --no-prompt "$filename" &
done

Pero eso solo funciona abriendo n ventanas para n archivos (si intenta usar la -sopción de WinMerge, no funcionará debido a que la herramienta difftool elimina los archivos temporales demasiado pronto)


Es por eso que me gusta el enfoque de GitDiff.bat - power-diffing con GI , que le permite revisar la lista de archivos con una diferencia, antes de seleccionar uno para examinar sus diferencias internas.
Lo modifiqué para usar solo comandos de DOS

@echo off

setlocal

if "%1" == "-?" (
    echo GitDiff - enables diffing of file lists, instead of having to serially
    echo diff files without being able to go back to a previous file.
    echo Command-line options are passed through to git diff.
    echo If GIT_FOLDER_DIFF is set, it is used to diff the file lists. Default is windff.
    goto END
)

if "%GIT_DIFF_COPY_FILES%"=="" (
    rd /s /q %TEMP%\GitDiff
    mkdir %TEMP%\GitDiff
    mkdir %TEMP%\GitDiff\old
    mkdir %TEMP%\GitDiff\new

    REM This batch file will be called by git diff. This env var indicates whether it is
    REM being called directly, or inside git diff
    set GIT_DIFF_COPY_FILES=1

    set GIT_DIFF_OLD_FILES=%TEMP%\GitDiff\old
    set GIT_DIFF_NEW_FILES=%TEMP%\GitDiff\new

    set GIT_EXTERNAL_DIFF=%~dp0\GitDiff.bat
    echo Please wait and press q when you see "(END)" printed in reverse color...
    call git diff %*

    if defined GIT_FOLDER_DIFF (
        REM This command using GIT_FOLDER_DIFF just does not work for some reason.
        %GIT_FOLDER_DIFF% %TEMP%\GitDiff\old %TEMP%\GitDiff\new
        goto END
    )

    if exist "%ProgramFiles%\Beyond Compare 2\BC2.exe" (
        set GIT_FOLDER_DIFF="%ProgramFiles%\Beyond Compare 2\BC2.exe"
        "%ProgramFiles%\Beyond Compare 2\BC2.exe" %TEMP%\GitDiff\old %TEMP%\GitDiff\new
        goto END
    )

    "%ProgramFiles(x86)%\WinMerge\WinMergeU.exe" -r -e -dl "Local" -dr "Remote"  %TEMP%\GitDiff\old %TEMP%\GitDiff\new
    goto END
)

REM diff is called by git with 7 parameters:
REM     path old-file old-hex old-mode new-file new-hex new-mode
copy %TEMP%\%~nx2 %GIT_DIFF_OLD_FILES%\%1
copy %5 %GIT_DIFF_NEW_FILES%

:END

No es lo suficientemente robusto para manejar archivos con los mismos nombres en diferentes directorios, pero le da una idea general de lo que es posible:
Aquí solo se abrirá un WinMerge, con la lista de archivos con diferencias internas. Puede hacer clic en los que desea examinar, luego un simple ESCcerrará todas las WinMerge-diffsesiones.

VonC
fuente
1
Intentando esto con git versión 1.6.5.1.1367.gcd48 y no parece generar ningún archivo en esas carpetas temporales. ¿Alguna idea de dónde buscar el problema? ¡Gracias!
Arte
@Art: en esos casos de depuración, trato de aislar el problema simplificando el script: 1 / si el script llamó con el parámetro 7 (primer paso de git diff, para copiar los archivos) 2 / es el script al menos llamado de nuevo al final de la git diff?
VonC
1
@Erik: con respecto a la opción -ub, consulte las preguntas frecuentes de WinMerge : es lo mismo que -u: le dice a WinMerge que no agregue los archivos a la MRU.
VonC
1
@Erik: debería ver la comparación de archivos en c:\Temp\GitDiff\oldy c:\Temp\GitDiff\new, no ' /tmp'. ¿Está seguro de que está ejecutando este programa de DOS desde una sesión de DOS (y no desde una sesión de bash)?
VonC
1
@coffeemakr no se evaluó ""en mi caso (ejecutando el git configcomando desde una CMD de Windows. Pero tiene razón: se evaluaría ""si se ejecutara desde un shell bash.)
VonC
19

Tuve problemas para usar la primera parte en 2 lugares y la arreglé de la siguiente manera

  1. El segundo comando para configurar winmerge.cmd requería una barra oblicua adicional en cmdline (antes de $ LOCAL y $ REMOTE), de lo contrario, cygwin estaba sustituyendo la variable en cmdline

    C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
    
  2. cambió el archivo winmerge.sh a (sin esto, estaba obteniendo un error de ruta derecha inválida)

    #!/bin/sh
    echo Launching WinMergeU.exe: "$(cygpath -aw "$1")" "$(cygpath -aw "$2")"
    "$PROGRAMFILES/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$(cygpath -aw "$1")" "$(cygpath -aw "$2")"
    
Gopi
fuente
3
Hice exactamente las instrucciones de VonC, pero recibía argumentos vacíos en mi script winmerge.sh. Usar barras adicionales resolvió el problema. ¡Gracias!
ashagi
6

Dado que el hilo se está volviendo confuso y bifurcado, aquí hay instrucciones consolidadas para el método WinMerge "--dir-diff" de Listado de directorios para msysgit Git Windows.

Paso 1 : cree un archivo llamado winmerge.sh en una ubicación accesible a su ruta (como /home/bin/winmerge.sh) con el siguiente contenido.

#!/bin/sh
echo Launching WinMergeU.exe: $1 $2
"$PROGRAMFILES/WinMerge/WinMergeU.exe" -r -ub -dl "Remote" -dr "Local" "$1" "$2"

Paso 2 : escribe los siguientes comandos en Git Bash para indicarle a git que use winmerge.sh como difftool (estas opciones se almacenan en /home/.gitconfig):

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

Paso 3 : ahora puede probar escribiendo el siguiente comando en Git Bash para iniciar su diferencia de WinMerge:

git difftool --dir-diff

Paso 4 : para un acceso más rápido, cree un alias para este comando agregando esta línea a .bashrc en su carpeta de inicio (o cree un archivo .bashrc con esta línea si el archivo aún no existe):

alias diffdir='git difftool --dir-diff'

Paso 5 : ahora puede ver rápidamente una diferencia en WinMerge simplemente escribiendo el siguiente comando en Git Bash

diffdir
robertcollier4
fuente
Sería útil que alguien le explicara el significado de $LOCALy $REMOTE.
Tola Odejayi
6

Tengo un script que configurará las herramientas Diff y Merge en la configuración de Git con los parámetros adecuados que no requieren un archivo .sh separado para existir. Parece que me está funcionando bien.

git config --global diff.tool winmerge
git config --global difftool.prompt false
git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\""

git config --global merge.tool winmerge
git config --global mergetool.prompt false
git config --global mergetool.winmerge.trustExitCode true
git config --global mergetool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\" \"\$BASE\" \"\$MERGED\""

Nota : se cita toda la parte .cmd para que los parámetros se enumeren en el .gitconfig correctamente

Alf47
fuente
1
El siguiente comando no funcionó para mí. git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\"" Nota: este comando debe ejecutarse desde un símbolo del sistema y no desde powershell. Agregar manualmente lo siguiente a mi [difftool "winmerge"]sección .gitconfig funcionó para mí: cmd = 'C:/Program Files (x86)/WinMerge/WinMergeU.exe' -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\"
Josh
1
No funcionó, pero con algunos cambios, funciona: cmd abierto como administrador, y ejecute: git config --global mergetool.winmerge.cmd "\"C:\Program Files (x86)\WinMerge\WinMergeU.exe\" -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"". Hubo algunas cadenas de escape incorrectas (tenga en cuenta algunas barras diagonales inversas no deseadas adicionales justo antes del $, supongo $que no es necesario escapar). Además, le faltaba un final "después WinMergeU?.exe. Corre git config --get mergetool.winmerge.cmdpara ver qué se ha configurado realmente. De todos modos, gracias por la no .shversión: +1!
falsarella
5

En Windows puedes hacerlo de esta manera:

1) Abra el archivo .gitconfig. Se encuentra en su directorio de inicio: c: \ users \ username.gitconfig

2) Agregue las líneas siguientes. Preste atención a las comillas simples que envuelven el camino a winmerge:

[diff]
    tool = winmerge
[difftool "winmerge"]
    cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e "$LOCAL" "$REMOTE"
[difftool]
    prompt = false
[merge]
    tool = winmerge
[mergetool "winmerge"]
    cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" \"$MERGED\" \"$REMOTE\"
[mergetool]
    keepBackup = false
    trustExitCode = false
Caner
fuente
También presta atención a las delanteras barras en lugar de barras invertidas en la ruta de comandos.
wisbucky
5

Sin configuración:

git difftool --tool winmerge

Asumiendo:

  • Winmerge está instalado
  • Git para Windows está instalado, desde "git versión 2.12.0.windows1" o superior (aunque es posible que versiones anteriores de git hayan introducido el comando).
John Bentley
fuente
Gracias, esta es la solución más simple
code4j
2

Estaba confundido acerca de por qué la solución se presentaba como un archivo por lotes de DOS, ya que mi instalación de Git venía con un shell bash. Tampoco pude ejecutar un contexto de DOS desde bash, así que intenté adaptar lo que se compartió anteriormente en un contexto de bash.

Ya que git diff parece ejecutar el comando especificado una vez para cada archivo, dividí mi solución en dos scripts bash:

Primero, configure gitprepdiff.shpara ser el difftool como se mencionó anteriormente

#!/bin/sh
#echo ...gitprepdiff.sh
cp -v $1 "$TMP/GitDiff/old/$2"
cp -v $2 "$TMP/GitDiff/new"

También noté que los resultados de los git configurecomandos se pueden encontrar y editar directamente enC:\Users\<username>\.gitconfigure

gitdiff.sh luego se ejecuta en la línea de comandos donde normalmente llamaría git diff

#!/bin/sh
#echo Running gitdiff.sh...

DIFFTEMP=$TMP/GitDiff

echo Deleting and re-creating $DIFFTEMP...
rm -rf $DIFFTEMP;
mkdir $DIFFTEMP;

echo Creating $DIFFTEMP/old...
mkdir $DIFFTEMP/old;

echo Creating $DIFFTEMP/new...
mkdir $DIFFTEMP/new;

git diff --name-only "$@" | while read filename; do
    git difftool "$@" --no-prompt "$filename";
done

"$PROGRAMFILES\WinMerge\WinMergeU.exe" -r -e -dl "Repository" -dr "Working" $LOCALAPPDATA\\Temp\\1\\GitDiff\\old $LOCALAPPDATA\\Temp\\1\\GitDiff\\new

También vale la pena señalar que, en mi instalación, /tmp(en bash) asignado a %LOCALAPPDATA%\Temp\1\(en Windows), por eso estoy usando este último en mi llamada a WinMerge.

Shawn South
fuente
2
¡Me cambié gitprepdiff.shpor #!/bin/sh #echo ...gitprepdiff.sh mkdir -vp "$TMP/GitDiff/old/$(dirname $2)" cp -v $1 "$TMP/GitDiff/old/$2" cp -v --parents $2 "$TMP/GitDiff/new"Gracias!
dobau
Parece ridículo pasar por tantos obstáculos para que esto funcione, pero lo hace. Obtiene todas las diferencias de archivo de una sola vez, como debería ser. También tuve que hacer los cambios mencionados por @dobau para manejar correctamente los archivos en los subdirectorios.
Tom
1
git config --global diff.tool winmerge
git config --global difftool.winmerge.cmd "\"$PROGRAMFILES\\WinMerge\\WinMergeU.exe\" -u -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\""
git config --global difftool.prompt false

Según el manual de la línea de comandos de WinMerge : "Los parámetros tienen como prefijo una barra inclinada (/) o un guión (-)"

Steve Lang
fuente