Используйте Winmerge внутри Git для создания файла diff

Есть ли способ использовать Winmerge внутри git для выполнения Diffs?

9 ответов

Решение

Обновление июнь 2015, 6 лет спустя:

Как подробно описано в " git mergetool winmerge ", простой git config diff.tool winmerge будет достаточно.

Git 2.5+ (Q2, 2015) теперь знает о Winmerge как инструменте сравнения или слияния!


Оригинальный ответ (2009-2012)

(msysgit, 1.6.5, сессия DOS)

Первая часть (с использованием winmerge) описана в разделе " Как просмотреть вывод" git 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 г. (два с половиной года спустя):

Сравнение каталогов вместо файла к файлу будет доступно в ближайшее время:
Смотрите [ОБЪЯВЛЕНИЕ] Git 1.7.11.rc1:

" git difftool "узнал" --dir-diff "возможность порождать внешние инструменты сравнения, которые могут сравнивать две иерархии каталогов за раз после заполнения двух временных каталогов, вместо того, чтобы запускать экземпляр внешнего инструмента один раз для пары файлов.

Смотрите " Патч difftool : учат difftool для обработки каталогов diffs ", и ответ" Сравнение каталогов Git ветвей "для более подробной информации.


Оригинальный скрипт difftool по каталогам (декабрь 2009)

Как упоминает Seba Illingworth в своем ответе, скрипт git-diffall.sh (также помещенный в путь) может сделать именно это:

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

Но это работает только при открытии n окон для n файлов (если вы пытаетесь использовать -s вариант WinMerge, он не будет работать из-за временного удаления файлов 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 сессия.

Я столкнулся с проблемой при использовании первой части в 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 на (без этого получал ошибку right-path-invalid)

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

Без конфигурации:

git difftool --tool winmerge

Предполагая, что:

  • Winmerge установлен
  • Установлен Git для Windows, начиная с "git version 2.12.0.windows1" или выше (хотя в более ранних версиях git могла быть введена команда).

На окнах вы можете сделать это следующим образом:

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

У меня есть скрипт, который установит инструменты 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.

Поскольку поток становится запутанным и раздвоенным, здесь представлены сводные инструкции для метода WinMerge для каталога 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

Я вижу здесь много длинных и запутанных ответов, поэтому публикую упрощенную и минимальную версию, которая работала у меня в 2021 году на Windows10.

       git config diff.tool winmerge
 git config --replace --global difftool.prompt false

Я был озадачен тем, почему решение было представлено в виде пакетного файла DOS, поскольку моя установка Git шла с оболочкой bash. Мне также не удалось запустить контекст 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.

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: "Параметры начинаются с символа косой черты ( /) или тире ( -)"

Другие вопросы по тегам