usa Winmerge all'interno di Git per file diff


Risposte:


113

Aggiornamento giugno 2015, 6 anni dopo:

Come spiegato in " git mergetool winmerge ", un semplice git config diff.tool winmergesarà sufficiente.

Git 2.5+ (Q2, 2015) è ora a conoscenza di Winmerge come strumento di differenza o unione!


Risposta originale (2009-2012)

(msysgit, 1.6.5, sessione DOS)

La prima parte (usando winmerge) è descritta in " Come posso visualizzare l'output di 'git diff' con il programma 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.shmemorizzato in una directory parte del tuo PATH:

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

(vedi Opzioni della riga di comando di WinMerge )

git difftool

lancerà ora WinMerge.
Se vuoi git diffavviare WinMerge, imposta semplicemente:

set GIT_EXTERNAL_DIFF=winmerge.sh

Ma il vero valore aggiunto deriva dalla possibilità di utilizzare lo stesso strumento diff per presentare tutte le differenze in un batch invece di presentarle in sequenza, costringendoti a chiudere le finestre dello strumento diff un file alla volta.

Aggiornamento giugno 2012 (2 anni e mezzo dopo):

Il confronto tra directory invece di file per file sarà presto disponibile:
Vedi [ANNOUNCE] Git 1.7.11.rc1 :

" git difftool" appreso " --dir-diff" l'opzione per generare strumenti di diff esterni che possono confrontare due gerarchie di directory contemporaneamente dopo aver popolato due directory temporanee, invece di eseguire un'istanza dello strumento esterno una volta per coppia di file .

Vedere " Patch difftool: insegnare difftoola gestire le differenze di directory " e la risposta " Confronto di directory dei rami Git " per maggiori dettagli.


Difftool originale per script directory (dicembre 2009)

Come afferma Seba Illingworth nella sua risposta , uno script git-diffall.sh (inserito anche nel percorso) può fare proprio questo:

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

Ma funziona solo aprendo n finestre per n file (se provi a utilizzare l' -sopzione di WinMerge, non funzionerà perché i file temporanei vengono eliminati troppo presto dal difftool)


Questo è il motivo per cui mi piace l'approccio di GitDiff.bat - power-diffing con GI , che consente di rivedere l'elenco dei file con una differenza, prima di selezionarne uno per esaminarne le differenze interne.
L'ho ottimizzato per utilizzare solo comandi 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

Non è abbastanza robusto per gestire file con lo stesso nome in directory diverse, ma ti dà un'idea generale di cosa è possibile:
qui si aprirà solo un WinMerge, con l'elenco dei file con differenze interne. Puoi fare clic su quelli che vuoi esaminare, quindi un semplice ESCchiuderà l'intera WinMerge-diffsessione.


1
Provando questo con la versione git 1.6.5.1.1367.gcd48 e non sembra generare alcun file in quelle cartelle temporanee. Qualche idea su dove cercare il problema? Grazie!
Arte

@Art: in quei casi di debug, cerco di isolare il problema semplificando lo script: 1 / se lo script chiama con il parametro 7 (primo passaggio di git diff, per copiare i file) 2 / lo script è almeno richiamato alla fine del git diff?
VonC

1
@Erik: per quanto riguarda l'opzione -ub, vedere le FAQ di WinMerge : è lo stesso di -u: dice a WinMerge di non aggiungere i file all'MRU.
VonC

1
@Erik: dovresti vedere il confronto dei file in c:\Temp\GitDiff\olde c:\Temp\GitDiff\new, non ' /tmp'. Sei sicuro di eseguire questo programma DOS da una sessione DOS (e non da una sessione bash)?
VonC

1
@coffeemakr non ha valutato ""nel mio caso (eseguendo il git configcomando da un CMD di Windows. Ma hai ragione: valuterà ""se eseguito da una shell bash.
VonC

19

Ho riscontrato problemi nell'utilizzo della prima parte in 2 punti e l'ho risolto come segue

  1. Il secondo comando per l'impostazione di winmerge.cmd richiedeva una barra extra su cmdline (prima di $ LOCAL e $ REMOTE), altrimenti cygwin stava sostituendo la variabile in cmdline

    C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
    
  2. cambiato il file winmerge.sh in (senza questo, riceveva un errore di percorso corretto non valido)

    #!/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")"
    

3
Ho seguito esattamente le istruzioni di VonC, ma ricevevo argomenti vuoti nel mio script winmerge.sh. L'uso di barre extra ha risolto il problema. Grazie!
Ashagi

6

Poiché il thread sta diventando confuso e biforcato, ecco le istruzioni consolidate per il metodo WinMerge dell'elenco di directory "--dir-diff" per msysgit Git Windows.

Passaggio 1 : crea un file denominato winmerge.sh in una posizione accessibile al tuo percorso (come /home/bin/winmerge.sh) con i seguenti contenuti.

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

Passaggio 2 : digitare i seguenti comandi in Git Bash per istruire git a utilizzare winmerge.sh come difftool (queste opzioni vengono memorizzate in /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

Passaggio 3 : ora puoi eseguire il test digitando il seguente comando in Git Bash per avviare il tuo WinMerge diff:

git difftool --dir-diff

Passaggio 4 : per un accesso più rapido, creare un alias per questo comando aggiungendo questa riga a .bashrc nella cartella home (o creare il file .bashrc con questa riga se il file non esiste già):

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

Passaggio 5 - Ora puoi vedere rapidamente una differenza in WinMerge semplicemente digitando il seguente comando in Git Bash

diffdir

Sarebbe utile avere qualcuno che spieghi i significati di $LOCALe $REMOTE.
Tola Odejayi

6

Ho uno script che imposterà gli strumenti Diff e Merge nella configurazione Git con i parametri corretti che non richiedono l'esistenza di un file .sh separato. Sembra che funzioni bene per me.

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 : l'intera porzione .cmd viene citata in modo che i parametri vengano elencati correttamente in .gitconfig


1
Il seguente comando non ha funzionato per me. git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\"" Nota: questo comando deve essere eseguito da un prompt dei comandi e non da PowerShell. L'aggiunta manuale di quanto segue alla mia [difftool "winmerge"]sezione .gitconfig ha funzionato per me: cmd = 'C:/Program Files (x86)/WinMerge/WinMergeU.exe' -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\"
Josh

1
Non ha funzionato, ma con alcune modifiche, funziona: cmd aperta come amministratore, ed eseguire: git config --global mergetool.winmerge.cmd "\"C:\Program Files (x86)\WinMerge\WinMergeU.exe\" -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"". C'erano alcune stringhe di escape errate (nota alcune barre rovesciate aggiuntive indesiderate lì subito prima del $- immagino $che non sia necessario eseguire l'escape). Inoltre, mancava una fine "dopo WinMergeU?.exe. Corri git config --get mergetool.winmerge.cmda vedere cosa era stato effettivamente impostato. Comunque, grazie per la mancata .shversione: +1!
falsarella

5

Su Windows puoi farlo in questo modo:

1) Apri il file .gitconfig. Si trova nella tua home directory: c: \ users \ username.gitconfig

2) Aggiungi le righe seguenti. Presta attenzione alle virgolette singole che racchiudono il percorso per 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

Prestare attenzione anche alle barre in avanti invece che alle barre rovesciate nel percorso del comando.
wisbucky

5

Senza configurazione:

git difftool --tool winmerge

Supponendo:

  • Winmerge è installato
  • Git per Windows è installato da "git versione 2.12.0.windows1" o superiore (sebbene le versioni precedenti di git possano aver introdotto il comando).

Grazie, questa è la soluzione più semplice
code4j

2

Ero confuso sul motivo per cui la soluzione è stata presentata come un file batch DOS, poiché la mia installazione di Git veniva fornita con una shell bash. Non sono stato inoltre in grado di ottenere un contesto DOS in esecuzione da bash, quindi ho tentato di adattare ciò che era precedentemente condiviso in un contesto bash.

Poiché git diffsembra che esegua il comando specificato una volta per ogni file, ho diviso la mia soluzione in due script bash:

Per prima cosa, configura gitprepdiff.shcome difftool come accennato in precedenza

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

Ho anche notato che i risultati dei git configurecomandi possono essere trovati e modificati direttamente inC:\Users\<username>\.gitconfigure

gitdiff.sh viene quindi eseguito dalla riga di comando dove normalmente chiameresti 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

Vale anche la pena notare che, sulla mia installazione, /tmp(in bash) mappato su %LOCALAPPDATA%\Temp\1\(in Windows), ecco perché sto usando quest'ultimo nella mia chiamata a WinMerge.


2
Sono cambiato gitprepdiff.shper #!/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"Grazie!
dobau

Sembra ridicolo saltare così tanti cerchi per far funzionare questo, ma lo fa. Ottieni tutte le differenze di file in una volta come dovrebbe essere. Ho dovuto apportare anche le modifiche menzionate da @dobau per gestire correttamente i file nelle sottodirectory.
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

Secondo il manuale della riga di comando di WinMerge : "I parametri sono preceduti da un carattere barra (/) o trattino (-)"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.