Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

Как указано в разделе git mergetool winmerge", достаточно простого git config diff.tool winmerge.

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


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

(msysgit, 1.6.5, сеанс DOS)

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

Но реальная добавленная стоимость исходит из возможности использовать тот же инструмент diff для для представления всех различий в одном пакете вместо того, чтобы представлять их последовательно, заставляя вас закрывать окна инструментов разметки одним файлом на время.

Обновление Июнь 2012 (через 2 с половиной года):

Сравнение каталогов вместо файлов по файлу будет доступно в ближайшее время:
См. [ANNOUNCE] Git 1.7.11.rc1:

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

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


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

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

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

Но это работает только при открытии n окон для n файлов (если вы пытаетесь использовать параметр -s для WinMerge, это не сработает из-за того, что временные файлы будут удалены с помощью diffftool слишком рано)


Вот почему мне нравится подход GitDiff.bat - мощное различие с 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

Я столкнулся с проблемой использования первой части в 2-х местах и ​​зафиксировал ее следующим образом

  • Вторая команда для настройки winmerge.cmd потребовала дополнительной косой черты в cmdline (до $LOCAL и $REMOTE), иначе cygwin заменил переменную в cmdline

    C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
    
  • изменил файл 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

Так как поток становится запутанным и раздвоенным, вот консолидированные инструкции для списка каталогов "-dir-diff" 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 как diffftool (эти параметры сохраняются в /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:

git difftool --dir-diff

Шаг 4. Для более быстрого доступа создайте псевдоним для этой команды, добавив эту строку в .bashrc в своей домашней папке (или создайте файл .bashrc с этой строкой, если файл еще не существует)

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

Шаг 5. Теперь вы можете быстро увидеть diff в WinMerge, просто введя следующую команду в Git Bash

diffdir

Ответ 4

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

Ответ 5

Я был смущен тем, почему решение было представлено как пакетный файл DOS, так как моя установка Git появилась с оболочкой bash. Я также не смог получить контекст DOS из bash, поэтому я попытался адаптировать то, что ранее было разделено в контексте bash.

Так как git diff, как представляется, запускает указанную команду один раз для каждого файла, я разбиваю свое решение на два сценария bash:

Сначала настройте gitprepdiff.sh как diffftool, как упоминалось ранее

#!/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 "[email protected]" | while read filename; do
    git difftool "[email protected]" --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.

Ответ 6

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

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

Ответ 7

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

git difftool --tool winmerge

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

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

Ответ 8

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