gunakan Winmerge di dalam Git untuk mengajukan diff

Jawaban:

113

Perbarui Juni 2015, 6 tahun kemudian:

Seperti yang dijelaskan dalam " git mergetool winmerge ", yang sederhana git config diff.tool winmergesudah cukup.

Git 2.5+ (Q2, 2015) sekarang mengenal Winmerge sebagai alat diff atau merge!


Jawaban asli (2009-2012)

(msysgit, 1.6.5, sesi DOS)

Bagian pertama (menggunakan winmerge) dijelaskan dalam " Bagaimana cara melihat keluaran 'git diff' dengan program 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

Dengan winmerge.shdisimpan di bagian direktori Anda PATH:

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

(lihat opsi baris perintah WinMerge )

git difftool

sekarang akan meluncurkan WinMerge.
Jika Anda ingin git diffmeluncurkan WinMerge, cukup setel:

set GIT_EXTERNAL_DIFF=winmerge.sh

Tetapi nilai tambah yang sebenarnya berasal dari kemampuan untuk menggunakan alat diff yang sama untuk menampilkan semua perbedaan dalam satu batch daripada menampilkannya secara berurutan, memaksa Anda untuk menutup file jendela alat diff satu per satu.

Perbarui Juni 2012 (2 setengah tahun kemudian):

Membandingkan direktori sebagai ganti file-demi-file akan segera tersedia:
Lihat [MENGUMUMKAN] Git 1.7.11.rc1 :

" git difftool" mempelajari opsi " --dir-diff" untuk memunculkan alat diff eksternal yang dapat membandingkan dua hierarki direktori sekaligus setelah mengisi dua direktori sementara, alih-alih menjalankan instance alat eksternal satu kali per pasangan file .

Lihat " Patch difftool: ajarkan difftooluntuk menangani direktori diffs ", dan jawaban " Perbandingan direktori cabang Git " untuk lebih jelasnya.


Difftool asli menurut skrip direktori (Desember 2009)

Seperti yang disebutkan Seba Illingworth dalam jawabannya , skrip git-diffall.sh (juga diletakkan di jalur) dapat melakukan hal itu:

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

Tetapi itu hanya berfungsi dengan membuka n windows untuk n file (jika Anda mencoba menggunakan -sopsi WinMerge, itu tidak akan berfungsi karena file temp dihapus oleh difftool terlalu dini)


Itulah mengapa saya menyukai pendekatan GitDiff.bat - power-diffing dengan GI , yang memungkinkan Anda untuk meninjau daftar file dengan perbedaan, sebelum memilih satu untuk memeriksa perbedaan internalnya.
Saya telah men-tweaknya untuk hanya menggunakan perintah 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

Tidak cukup kuat untuk menangani file dengan nama yang sama di direktori yang berbeda, tetapi memberi Anda gambaran umum tentang apa yang mungkin:
Di sini hanya satu WinMerge yang akan terbuka, dengan daftar file yang memiliki perbedaan internal. Anda dapat mengklik salah satu yang ingin Anda periksa, lalu simple ESCakan menutup semua WinMerge-diffsesi.

VonC
sumber
1
Mencoba ini dengan git versi 1.6.5.1.1367.gcd48 dan tampaknya tidak menghasilkan file apa pun di folder temp tersebut. Ada ide di mana mencari masalah? Terima kasih!
Seni
@Art: dalam kasus debug tersebut, saya mencoba mengisolasi masalah dengan menyederhanakan skrip: 1 / jika skrip dipanggil dengan parameter 7 (lewati pertama git diff, untuk menyalin file) 2 / adalah skrip setidaknya dipanggil kembali di akhir git diff?
VonC
1
@Erik: mengenai opsinya -ub, lihat FAQ WinMerge : ini sama dengan -u: ini memberitahu WinMerge untuk tidak menambahkan file ke MRU.
VonC
1
@Erik: Anda harus melihat perbandingan file dalam c:\Temp\GitDiff\olddan c:\Temp\GitDiff\new, bukan ' /tmp'. Apakah Anda yakin menjalankan program DOS ini dari sesi DOS (dan bukan sesi bash)?
VonC
1
@coffeemakr itu tidak mengevaluasi ""dalam kasus saya (menjalankan git configperintah dari CMD Windows. Tetapi Anda benar: itu akan mengevaluasi ""jika dijalankan dari shell bash.
VonC
19

Saya menghadapi masalah saat menggunakan bagian pertama di 2 tempat dan memperbaikinya sebagai berikut

  1. Perintah kedua untuk menyiapkan winmerge.cmd membutuhkan garis miring ekstra pada cmdline (sebelum $ LOCAL dan $ REMOTE), jika tidak cygwin mengganti variabel di cmdline

    C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
    
  2. mengubah file winmerge.sh menjadi (tanpa ini, mendapatkan kesalahan jalur kanan-tidak valid)

    #!/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
sumber
3
Saya melakukan persis seperti yang diinstruksikan VonC, tetapi saya menerima argumen kosong di skrip winmerge.sh saya. Menggunakan garis miring ekstra menyelesaikan masalah. Terima kasih!
ashagi
6

Karena utas semakin membingungkan dan bercabang, berikut adalah petunjuk gabungan untuk metode WinMerge "--dir-diff" Daftar Direktori untuk msysgit Git Windows.

Langkah 1 - Buat file bernama winmerge.sh di lokasi yang dapat diakses oleh jalur Anda (seperti /home/bin/winmerge.sh) dengan konten berikut.

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

Langkah 2 - Ketik perintah berikut di Git Bash untuk menginstruksikan git menggunakan winmerge.sh sebagai difftool (opsi ini disimpan di /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

Langkah 3 - Sekarang Anda dapat menguji dengan mengetik perintah berikut di Git Bash untuk memulai perbedaan WinMerge Anda:

git difftool --dir-diff

Langkah 4 - Untuk akses yang lebih cepat, buat alias untuk perintah ini dengan menambahkan baris ini ke .bashrc di folder utama Anda (atau buat file .bashrc dengan baris ini jika file belum ada):

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

Langkah 5 - Sekarang Anda dapat dengan cepat melihat perbedaan di WinMerge hanya dengan mengetikkan perintah berikut ke Git Bash

diffdir
robertcollier4
sumber
Akan sangat membantu jika seseorang menjelaskan arti dari $LOCALdan $REMOTE.
Tola Odejayi
6

Saya memiliki skrip yang akan mengatur alat Diff dan Merge di konfigurasi Git dengan parameter yang tepat yang tidak memerlukan file .sh terpisah. Sepertinya bekerja dengan baik untuk saya.

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\""

Catatan - seluruh bagian .cmd dikutip sehingga parameter akan terdaftar di .gitconfig dengan benar

Alf47
sumber
1
Perintah berikut tidak berhasil untuk saya. git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\"" Catatan: Perintah ini harus dijalankan dari prompt perintah dan bukan dari PowerShell. Menambahkan secara manual berikut ini ke [difftool "winmerge"]bagian .gitconfig saya berhasil untuk saya: cmd = 'C:/Program Files (x86)/WinMerge/WinMergeU.exe' -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\"
Josh
1
Ini tidak bekerja, tetapi dengan beberapa perubahan, kerjanya: cmd terbuka sebagai administrator, dan menjalankan: git config --global mergetool.winmerge.cmd "\"C:\Program Files (x86)\WinMerge\WinMergeU.exe\" -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"". Ada beberapa string lolos yang salah (perhatikan beberapa garis miring terbalik yang tidak diinginkan di sana tepat sebelum $- saya kira $tidak perlu di-escape). Juga, itu kehilangan akhir "setelahnya WinMergeU?.exe. Jalankan git config --get mergetool.winmerge.cmduntuk melihat apa yang sebenarnya telah diatur. Pokoknya, terima kasih untuk .shversi non : +1!
falsarella
5

Di windows, Anda dapat melakukannya dengan cara ini:

1) Buka file .gitconfig. Itu terletak di direktori home Anda: c: \ users \ username.gitconfig

2) Tambahkan baris di bawah ini. Perhatikan tanda kutip tunggal yang membungkus jalan menuju 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
sumber
Perhatikan juga garis miring ke depan, bukan garis miring terbalik di jalur perintah.
wisbucky
5

Tanpa konfigurasi:

git difftool --tool winmerge

Asumsi:

  • Winmerge diinstal
  • Git untuk Windows diinstal, dari "git versi 2.12.0.windows1" atau yang lebih baru (walaupun versi git sebelumnya mungkin telah memperkenalkan perintah tersebut).
John Bentley
sumber
Terima kasih, ini adalah solusi paling sederhana
code4j
2

Saya bingung mengapa solusi tersebut disajikan sebagai file batch DOS, karena instalasi Git saya dilengkapi dengan shell bash. Saya juga tidak bisa menjalankan konteks DOS dari bash, jadi saya mencoba menyesuaikan apa yang sebelumnya dibagikan dalam konteks bash.

Karena git difftampaknya menjalankan perintah yang ditentukan sekali untuk setiap file, saya membagi solusi saya menjadi dua skrip bash:

Pertama, konfigurasikan gitprepdiff.shmenjadi difftool seperti yang disebutkan sebelumnya

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

Saya juga mencatat bahwa hasil dari git configureperintah dapat ditemukan dan diedit langsung diC:\Users\<username>\.gitconfigure

gitdiff.sh kemudian dijalankan pada baris perintah yang biasa Anda panggil 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

Juga perlu diperhatikan adalah bahwa, pada instalasi saya, /tmp(dalam bash) dipetakan ke %LOCALAPPDATA%\Temp\1\(di Windows), jadi itulah mengapa saya menggunakan yang terakhir dalam panggilan saya ke WinMerge.

Shawn South
sumber
2
Saya berubah gitprepdiff.shuntuk #!/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"Terima Kasih!
dobau
Tampaknya konyol untuk melompati begitu banyak rintangan untuk membuat ini berhasil, tetapi ternyata berhasil. Anda mendapatkan semua diff file sekaligus sebagaimana mestinya. Saya harus membuat perubahan yang disebutkan oleh @dobau juga untuk menangani file di subdirektori dengan benar.
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

Sesuai dengan manual baris perintah WinMerge : "Parameter diawali dengan karakter garis miring (/) atau tanda hubung (-)"

Steve Lang
sumber