ใช้ Winmerge ภายใน Git เพื่อไฟล์ diff


คำตอบ:


114

อัปเดตมิถุนายน 2015 6 ปีต่อมา:

ตามรายละเอียดใน " git mergetool winmerge " ง่ายๆgit config diff.tool winmergeก็เพียงพอแล้ว

Git 2.5+ (Q2, 2015) ได้รับการยอมรับว่า Winmerge เป็นเครื่องมือที่แตกต่างหรือผสาน!


คำตอบเดิม (2009-2012)

(msysgit, 1.6.5, เซสชัน DOS)

ส่วนแรก (ใช้ WinMerge) อธิบายไว้ใน " ฉันจะดู 'คอมไพล์ diff' เอาท์พุทกับโปรแกรม 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

ด้วยการwinmerge.shเก็บไว้ในส่วนไดเรกทอรีที่คุณPATH:

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

(ดูตัวเลือกบรรทัดคำสั่ง WinMerge )

git difftool

ตอนนี้จะเปิด WinMerge
หากคุณต้องการgit diffเปิด WinMerge ให้ตั้งค่า:

set GIT_EXTERNAL_DIFF=winmerge.sh

แต่มูลค่าเพิ่มที่แท้จริงนั้นมาจากความสามารถในการใช้เครื่องมือที่แตกต่างกันเพื่อนำเสนอความแตกต่างทั้งหมดในชุดเดียวแทนที่จะนำเสนอตามลำดับบังคับให้คุณปิดหน้าต่างเครื่องมือต่างทีละไฟล์

อัปเดตมิถุนายน 2012 (2 ปีครึ่งหลังจากนั้น):

การเปรียบเทียบไดเร็กทอรีแทนการใช้ทีละไฟล์จะพร้อมใช้งานเร็ว ๆ นี้:
ดู[ประกาศ] Git 1.7.11.rc1 :

" git difftool" เรียนรู้ " --dir-diff" เลือกที่จะวางไข่เครื่องมือ diff ภายนอกที่สามารถเปรียบเทียบสองลำดับชั้นไดเรกทอรีในช่วงเวลาหลังจากที่ประชากรของสองไดเรกทอรีชั่วคราวแทนที่จะวิ่งตัวอย่างของเครื่องมือภายนอกหนึ่งครั้งต่อคู่ไฟล์

โปรดดูที่ " แพทช์difftool: สอนdifftoolการ diffs จับไดเรกทอรี " และคำตอบ " เปรียบเทียบไดเรกทอรีของ Git สาขา " สำหรับรายละเอียดเพิ่มเติม


ต้นฉบับ difftool โดยไดเร็กทอรีสคริปต์ (ธันวาคม 2552)

ดังที่Seba Illingworthกล่าวไว้ในคำตอบของเขาสคริปต์ git-diffall.sh (วางในเส้นทางด้วย) สามารถทำสิ่งนั้นได้:

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

แต่ใช้งานได้โดยการเปิดn windows สำหรับnไฟล์เท่านั้น (หากคุณพยายามใช้-sตัวเลือกของ WinMerge มันจะไม่ทำงานเนื่องจากไฟล์ temp ถูกลบโดย difftool เร็วเกินไป)


นั่นคือเหตุผลที่ฉันชอบแนวทางของGitDiff.bat - power-diffing กับ GIซึ่งช่วยให้คุณตรวจสอบรายการไฟล์ด้วยความแตกต่างก่อนที่จะเลือกไฟล์เพื่อตรวจสอบความแตกต่างภายใน
ฉันปรับแต่งให้ใช้เฉพาะคำสั่ง 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

ไม่แข็งแรงพอที่จะจัดการไฟล์ที่มีชื่อเดียวกันในไดเรกทอรีต่างกัน แต่จะช่วยให้คุณมีแนวคิดทั่วไปเกี่ยวกับสิ่งที่เป็นไปได้: ที่
นี่จะมี WinMerge เพียงตัวเดียวเท่านั้นที่จะเปิดขึ้นโดยรายชื่อไฟล์ที่มีความแตกต่างภายใน คุณสามารถคลิกที่สิ่งที่คุณต้องการตรวจสอบจากนั้นขั้นตอนง่ายๆESCจะปิดWinMerge-diffเซสชันทั้งหมด


1
ลองใช้ git เวอร์ชัน 1.6.5.1.1367.gcd48 และดูเหมือนว่าจะไม่สร้างไฟล์ใด ๆ ในโฟลเดอร์ temp เหล่านั้น มีความคิดที่จะค้นหาปัญหาหรือไม่? ขอบคุณ!
ศิลปะ

@Art: ในกรณีการดีบักเหล่านั้นฉันพยายามแยกปัญหาโดยการทำให้สคริปต์ง่ายขึ้น: 1 / ถ้าสคริปต์เรียกด้วยพารามิเตอร์ 7 (ส่งผ่าน git ครั้งแรกเพื่อคัดลอกไฟล์) 2 / เป็นสคริปต์ที่เรียกกลับอย่างน้อย ในตอนท้ายของgit diff?
VonC

1
@Erik: เกี่ยวกับตัวเลือก-ubโปรดดูคำถามที่พบบ่อยของ WinMerge : มันเหมือนกับ-u: มันบอกให้ WinMerge ไม่เพิ่มไฟล์ลงใน MRU
VonC

1
@Erik: คุณควรเห็นการเปรียบเทียบไฟล์ในc:\Temp\GitDiff\oldและc:\Temp\GitDiff\newไม่ใช่ ' /tmp' คุณแน่ใจหรือไม่ว่ากำลังเรียกใช้โปรแกรม DOS นี้จากเซสชัน DOS (ไม่ใช่เซสชันทุบตี)
VonC

1
@coffeemakr มันไม่ได้ประเมิน""ในกรณีของฉัน (ดำเนินการgit configคำสั่งจาก Windows CMD แต่คุณพูดถูก: มันจะประเมิน""ว่าดำเนินการจาก bash shell หรือไม่
VonC

19

ฉันประสบปัญหาในการใช้ส่วนแรกใน 2 ที่และแก้ไขได้ดังนี้

  1. คำสั่งที่สองสำหรับการตั้งค่า winmerge.cmd ต้องใช้เครื่องหมายทับพิเศษบน cmdline (ก่อน $ LOCAL และ $ REMOTE) มิฉะนั้น cygwin จะแทนที่ตัวแปรใน cmdline

    C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
    
  2. เปลี่ยนไฟล์ winmerge.sh เป็น (หากไม่มีสิ่งนี้ได้รับข้อผิดพลาดทางขวา - ไม่ถูกต้อง)

    #!/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
ฉันทำตามที่ VonC สั่ง แต่ฉันได้รับอาร์กิวเมนต์ว่างเปล่าในสคริปต์ winmerge.sh ของฉัน การใช้เครื่องหมายทับพิเศษช่วยแก้ปัญหาได้ ขอบคุณ!
ashagi

6

เนื่องจากเธรดเริ่มสับสนและมีการแยกส่วนต่อไปนี้เป็นคำแนะนำที่รวมไว้สำหรับวิธีการ WinMerge "--dir-diff" สำหรับ msysgit Git Windows

ขั้นตอนที่ 1 - สร้างไฟล์ชื่อ winmerge.sh ในตำแหน่งที่สามารถเข้าถึงเส้นทางของคุณ (เช่น /home/bin/winmerge.sh) โดยมีเนื้อหาต่อไปนี้

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

ขั้นตอนที่ 2 - พิมพ์คำสั่งต่อไปนี้ใน Git Bash เพื่อสั่งให้ git ใช้ winmerge.sh เป็น difftool (ตัวเลือกเหล่านี้จะถูกเก็บไว้ใน /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

ขั้นตอนที่ 3 - ตอนนี้คุณสามารถทดสอบได้โดยพิมพ์คำสั่งต่อไปนี้ใน Git Bash เพื่อเริ่ม WinMerge diff ของคุณ:

git difftool --dir-diff

ขั้นตอนที่ 4 - เพื่อการเข้าถึงที่รวดเร็วยิ่งขึ้นให้สร้างนามแฝงสำหรับคำสั่งนี้โดยเพิ่มบรรทัดนี้เป็น. bashrc ในโฟลเดอร์บ้านของคุณ (หรือสร้างไฟล์. bashrc ด้วยบรรทัดนี้หากไม่มีไฟล์อยู่แล้ว):

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

ขั้นตอนที่ 5 - ตอนนี้คุณสามารถเห็นความแตกต่างใน WinMerge ได้อย่างรวดเร็วเพียงแค่พิมพ์คำสั่งต่อไปนี้ใน Git Bash

diffdir

มันจะเป็นประโยชน์ที่จะมีคนอธิบายความหมายของและ$LOCAL $REMOTE
Tola Odejayi

6

ฉันมีสคริปต์ที่จะตั้งค่าเครื่องมือ Diff และ Merge ในการกำหนดค่า Git ด้วยพารามิเตอร์ที่เหมาะสมซึ่งไม่จำเป็นต้องมีไฟล์. sh แยกต่างหาก ดูเหมือนว่าจะทำงานได้ดีสำหรับฉัน

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

หมายเหตุ - ส่วน. cmd ทั้งหมดถูกยกมาเพื่อให้พารามิเตอร์แสดงรายการใน. gitconfig อย่างถูกต้อง


1
คำสั่งต่อไปนี้ใช้ไม่ได้สำหรับฉัน git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\"" หมายเหตุ: คำสั่งนี้ต้องเรียกใช้จากพรอมต์คำสั่งไม่ใช่จาก powershell การเพิ่มสิ่งต่อไปนี้ใน[difftool "winmerge"]ส่วน. gitconfig ด้วยตนเองได้ผลสำหรับฉัน: cmd = 'C:/Program Files (x86)/WinMerge/WinMergeU.exe' -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\"
Josh

1
มันไม่ได้ทำงาน แต่มีการเปลี่ยนแปลงบางอย่างก็ทำงาน: cmd git config --global mergetool.winmerge.cmd "\"C:\Program Files (x86)\WinMerge\WinMergeU.exe\" -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\""เปิดในฐานะผู้ดูแลการทำงาน: มีสตริง Escape ที่ไม่ถูกต้องอยู่สองสามตัว (สังเกตแบ็กสแลชที่ไม่ต้องการเพิ่มเติมสองสามอันตรงนี้ก่อน$- ฉันเดาว่า$ไม่จำเป็นต้องใช้ Escape) นอกจากนี้ยังไม่มีจุดจบ"หลังจากWinMergeU?.exeนั้น วิ่งgit config --get mergetool.winmerge.cmdไปดูสิ่งที่ตั้งไว้จริง ยังไงก็ขอบคุณสำหรับ.shรุ่นที่ไม่ใช่: +1!
falsarella

5

บน windows คุณสามารถทำได้ด้วยวิธีนี้:

1) เปิดไฟล์. gitconfig อยู่ที่โฮมไดเร็กทอรีของคุณ: c: \ users \ username.gitconfig

2) เพิ่มบรรทัดด้านล่าง ให้ความสนใจกับคำพูดเดียวที่ตัดเส้นทางสู่ 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

นอกจากนี้ยังให้ความสนใจกับไปข้างหน้าทับแทน backslashes ในเส้นทางคำสั่ง
wisbucky

5

ไม่มีการกำหนดค่า:

git difftool --tool winmerge

สมมติว่า:

  • ติดตั้ง Winmerge แล้ว
  • มีการติดตั้ง Git สำหรับ windows ตั้งแต่ "git เวอร์ชัน 2.12.0.windows1" ขึ้นไป (แม้ว่า git เวอร์ชันก่อนหน้าอาจมีคำสั่ง)

ขอบคุณนี่เป็นทางออกที่ง่ายที่สุด
code4j

2

ฉันสับสนว่าทำไมโซลูชันจึงถูกนำเสนอเป็นไฟล์แบตช์ DOS เนื่องจากการติดตั้ง Git ของฉันมาพร้อมกับ bash shell ฉันยังไม่สามารถรับบริบท DOS ที่เรียกใช้จาก bash ได้ดังนั้นฉันจึงพยายามปรับเปลี่ยนสิ่งที่แชร์ก่อนหน้านี้ในบริบท bash

เนื่องจากgit diffดูเหมือนว่าจะเรียกใช้คำสั่งที่ระบุหนึ่งครั้งสำหรับแต่ละไฟล์ฉันจึงแยกโซลูชันของฉันออกเป็นสองสคริปต์ bash:

ขั้นแรกกำหนดค่าgitprepdiff.shให้เป็น difftool ตามที่กล่าวไว้ก่อนหน้านี้

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

ฉันสังเกตด้วยว่าผลลัพธ์ของgit configureคำสั่งสามารถพบและแก้ไขได้โดยตรงในไฟล์C:\Users\<username>\.gitconfigure

gitdiff.sh จากนั้นเรียกใช้ที่บรรทัดคำสั่งที่คุณจะเรียกตามปกติ 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

สิ่งที่น่าสังเกตก็คือในการติดตั้งของฉัน/tmp(ใน bash) แมปกับ%LOCALAPPDATA%\Temp\1\(ใน Windows) ดังนั้นฉันจึงใช้สิ่งหลังในการโทรไปที่ WinMerge


2
ฉันเปลี่ยนไปgitprepdiff.shเพื่อ#!/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"ขอบคุณ!
dobau

ดูเหมือนจะไร้สาระที่จะกระโดดผ่านห่วงมากมายเพื่อให้ทำงานนี้ แต่มันก็ทำได้ คุณจะได้ไฟล์ทั้งหมดที่แตกต่างกันในครั้งเดียวอย่างที่ควรจะเป็น ฉันต้องทำการเปลี่ยนแปลงที่กล่าวถึงโดย @dobau ด้วยเพื่อจัดการไฟล์ในไดเร็กทอรีย่อยอย่างถูกต้อง
ทอม

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

ตามคู่มือบรรทัดคำสั่ง WinMerge : "พารามิเตอร์ขึ้นต้นด้วยเครื่องหมายทับ (/) หรือขีด (-)"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.