sử dụng Winmerge bên trong Git để tạo tệp khác biệt


Câu trả lời:


113

Cập nhật tháng 6 năm 2015, 6 năm sau:

Như đã trình bày chi tiết trong " git mergetool winmerge ", một cách đơn giản git config diff.tool winmergelà đủ.

Git 2.5+ (Quý 2, 2015) hiện đã biết Winmerge như một công cụ khác biệt hoặc hợp nhất!


Câu trả lời gốc (2009-2012)

(msysgit, 1.6.5, phiên DOS)

Phần đầu tiên (sử dụng winmerge) được mô tả trong " Làm cách nào để xem đầu ra 'git diff' với chương trình 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

Với winmerge.shđược lưu trữ trong một phần thư mục của PATH:

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

(xem Tùy chọn dòng lệnh WinMerge )

git difftool

bây giờ sẽ khởi chạy WinMerge.
Nếu bạn muốn git diffkhởi chạy WinMerge, chỉ cần đặt:

set GIT_EXTERNAL_DIFF=winmerge.sh

Nhưng giá trị gia tăng thực sự đến từ khả năng sử dụng cùng một công cụ khác biệt đó để trình bày tất cả các khác biệt trong một lô thay vì trình bày chúng tuần tự, buộc bạn phải đóng cửa sổ công cụ khác biệt từng tệp một.

Cập nhật tháng 6 năm 2012 (2 năm rưỡi sau):

Tính năng so sánh thư mục thay vì từng tệp sẽ sớm khả dụng:
Xem [ANNOUNCE] Git 1.7.11.rc1 :

" git difftool" đã học được --dir-difftùy chọn "" để tạo ra các công cụ khác biệt bên ngoài có thể so sánh hai cấu trúc phân cấp thư mục tại một thời điểm sau khi điền hai thư mục tạm thời, thay vì chạy một phiên bản của công cụ bên ngoài một lần cho mỗi cặp tệp .

Xem "Bản difftool: dạy difftoolcách xử lý các điểm khác biệt thư mục " và câu trả lời " So sánh thư mục của các nhánh Git " để biết thêm chi tiết.


Bản gốc difftool của thư mục script (tháng 12 năm 2009)

Như Seba Illingworth đã đề cập trong câu trả lời của mình , một script git-diffall.sh (cũng được đặt trong đường dẫn) có thể làm điều đó:

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

Nhưng điều đó chỉ hoạt động bằng cách mở n cửa sổ cho n tệp (nếu bạn cố gắng sử dụng -stùy chọn của WinMerge, nó sẽ không hoạt động vì tệp tạm thời bị xóa bởi bộ khuếch tán quá sớm)


Đó là lý do tại sao tôi thích cách tiếp cận của GitDiff.bat - power-diffing với GI , cho phép bạn xem lại danh sách các tệp có sự khác biệt, trước khi chọn một tệp để kiểm tra sự khác biệt bên trong của nó.
Tôi đã điều chỉnh nó để chỉ sử dụng các lệnh 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

Nó không đủ mạnh để xử lý các tệp có cùng tên trong các thư mục khác nhau, nhưng nó cung cấp cho bạn một ý tưởng chung về những gì có thể:
Ở đây chỉ có một WinMerge sẽ mở ra, với danh sách các tệp có sự khác biệt nội bộ. Bạn có thể nhấp vào những cái bạn muốn kiểm tra, sau đó một thao tác đơn giản ESCsẽ đóng tất cả WinMerge-diffphiên.


1
Thử điều này với phiên bản git 1.6.5.1.1367.gcd48 và nó dường như không tạo bất kỳ tệp nào trong các thư mục tạm thời đó. Bất kỳ ý tưởng nơi để tìm kiếm vấn đề? Cảm ơn!
Art

@Art: trong những trường hợp gỡ lỗi đó, tôi cố gắng cô lập vấn đề bằng cách đơn giản hóa tập lệnh: 1 / nếu tập lệnh được gọi với tham số 7 (truyền đầu tiên của git diff, để sao chép tệp) 2 / tập lệnh có ít nhất được gọi lại không ở cuối git diff?
VonC

1
@Erik: về tùy chọn này -ub, hãy xem Câu hỏi thường gặp về WinMerge : nó giống như vậy -u: nó yêu cầu WinMerge không thêm tệp vào MRU.
VonC

1
@Erik: bạn sẽ thấy so sánh các tệp trong c:\Temp\GitDiff\oldc:\Temp\GitDiff\newkhông phải là /tmp''. Bạn có chắc chắn đang thực thi chương trình DOS này từ một phiên DOS (chứ không phải phiên bash) không?
VonC

1
@coffeemakr nó không đánh giá ""trong trường hợp của tôi (thực hiện git configlệnh từ Windows CMD. Nhưng bạn nói đúng: nó sẽ đánh giá ""nếu được thực thi từ bash shell.
VonC

19

Tôi đã gặp sự cố khi sử dụng phần đầu tiên ở 2 nơi và đã sửa nó như sau

  1. Lệnh thứ hai để thiết lập winmerge.cmd yêu cầu thêm một dấu gạch chéo trên cmdline (trước $ LOCAL và $ REMOTE), nếu không cygwin đang thay thế biến trong cmdline

    C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
    
  2. đã thay đổi tệp winmerge.sh thành (không có tệp này, nhận được lỗi đường dẫn bên phải-không hợp lệ)

    #!/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
Tôi đã thực hiện chính xác như cách VonC hướng dẫn, nhưng tôi nhận được các đối số trống trong tập lệnh winmerge.sh của mình. Sử dụng thêm dấu gạch chéo đã giải quyết được vấn đề. Cảm ơn bạn!
ashagi

6

Vì luồng đang trở nên khó hiểu và phân nhánh, đây là hướng dẫn tổng hợp cho phương pháp WinMerge "--dir-diff" của Danh sách thư mục dành cho msysgit Git Windows.

Bước 1 - Tạo một tệp có tên winmerge.sh tại một vị trí có thể truy cập vào đường dẫn của bạn (chẳng hạn như /home/bin/winmerge.sh) với nội dung sau.

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

Bước 2 - Nhập các lệnh sau vào Git Bash để hướng dẫn git sử dụng winmerge.sh làm difftool (các tùy chọn này được lưu trữ trong /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

Bước 3 - Bây giờ bạn có thể kiểm tra bằng cách gõ lệnh sau vào Git Bash để bắt đầu khác biệt WinMerge của bạn:

git difftool --dir-diff

Bước 4 - Để truy cập nhanh hơn, hãy tạo bí danh cho lệnh này bằng cách thêm dòng này vào .bashrc trong thư mục chính của bạn (hoặc tạo tệp .bashrc với dòng này nếu tệp chưa tồn tại):

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

Bước 5 - Bây giờ bạn có thể nhanh chóng thấy sự khác biệt trong WinMerge chỉ bằng cách gõ lệnh sau vào Git Bash

diffdir

Sẽ rất hữu ích nếu ai đó giải thích ý nghĩa của $LOCAL$REMOTE.
Tola Odejayi

6

Tôi có một tập lệnh sẽ đặt các công cụ Diff và Merge trong cấu hình Git với các tham số thích hợp không yêu cầu tồn tại tệp .sh riêng biệt. Nó dường như đang hoạt động tốt cho tôi.

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

Lưu ý - toàn bộ phần .cmd được trích dẫn để các tham số sẽ được liệt kê trong .gitconfig đúng cách


1
Lệnh sau không hoạt động đối với tôi. git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\"" Lưu ý: Lệnh này phải được chạy từ dấu nhắc lệnh chứ không phải từ quyền hạn. Việc thêm thủ công phần sau vào [difftool "winmerge"]phần .gitconfig của tôi đã mang lại hiệu quả cho tôi: cmd = 'C:/Program Files (x86)/WinMerge/WinMergeU.exe' -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\"
Josh,

1
Nó không làm việc, nhưng với một số thay đổi, nó hoạt động: cmd mở as administrator, và chạy: 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ó một vài chuỗi thoát không chính xác (lưu ý một vài dấu gạch chéo ngược không mong muốn bổ sung ở đó ngay trước $- Tôi đoán $không cần phải thoát). Ngoài ra, nó đã thiếu một kết thúc "sau đó WinMergeU?.exe. Chạy git config --get mergetool.winmerge.cmdđể xem những gì đã thực sự được thiết lập. Dù sao, cảm ơn cho .shphiên bản không phải : +1!
falsarella

5

Trên windows, bạn có thể thực hiện theo cách này:

1) Mở tệp .gitconfig. Nó nằm trong thư mục chính của bạn: c: \ users \ username.gitconfig

2) Thêm các dòng bên dưới. Hãy chú ý đến các dấu ngoặc kép bao quanh đường dẫn đến 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

Cũng chú ý đến các dấu gạch chéo về phía trước thay vì dấu gạch chéo ngược trong đường dẫn lệnh.
khôn ngoan

5

Không có cấu hình:

git difftool --tool winmerge

Giả định:

  • Winmerge đã được cài đặt
  • Git cho windows được cài đặt, từ "git phiên bản 2.12.0.windows1" trở lên (mặc dù các phiên bản git trước đó có thể đã giới thiệu lệnh).

Cảm ơn, đây là giải pháp đơn giản nhất
code4j

2

Tôi đã nhầm lẫn về lý do tại sao giải pháp được trình bày dưới dạng tệp lô DOS, vì cài đặt Git của tôi đi kèm với trình bao bash. Tôi cũng không thể tải ngữ cảnh DOS chạy từ bash, vì vậy tôi đã cố gắng điều chỉnh những gì đã được chia sẻ trước đó trong ngữ cảnh bash.

Từ git diff dường như chạy lệnh được chỉ định một lần cho mỗi tệp, tôi chia giải pháp của mình thành hai tập lệnh bash:

Đầu tiên, hãy cấu hình gitprepdiff.shđể trở thành bộ khuếch tán như đã đề cập trước đó

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

Tôi cũng lưu ý rằng kết quả của các git configurelệnh có thể được tìm thấy và chỉnh sửa trực tiếp trongC:\Users\<username>\.gitconfigure

gitdiff.sh sau đó chạy ở dòng lệnh mà bạn thường gọi 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

Cũng cần lưu ý rằng, trên cài đặt của tôi, /tmp(trong bash) được ánh xạ tới %LOCALAPPDATA%\Temp\1\(trong Windows), vì vậy đó là lý do tại sao tôi sử dụng cái sau trong cuộc gọi tới WinMerge.


2
Tôi đã thay đổi 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"Thank You!
dobau

Có vẻ vô lý khi nhảy qua rất nhiều vòng để làm cho điều này thành công, nhưng nó đã làm được. Bạn nhận được tất cả các khác biệt của tệp trong một lần như nó phải như vậy. Tôi cũng phải thực hiện các thay đổi mà @dobau đề cập để xử lý đúng cách các tệp trong thư mục con.
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

Theo hướng dẫn sử dụng dòng lệnh WinMerge : "Các tham số được bắt đầu bằng ký tự dấu gạch chéo (/) hoặc dấu gạch ngang (-)"

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.