Как просмотреть вывод 'git diff' с помощью моего предпочтительного инструмента сравнения/средства просмотра?

Когда я набираю git diff, я хочу просмотреть результат с помощью моего средства визуального сравнения (SourceGear "diffmerge" в Windows). Как настроить git для этого?

Ответ 1

Начиная с Git1.6.3, вы можете использовать скрипт git difftool: см. Мой ответ ниже.


Может быть, эта статья поможет вам. Вот лучшие части:

Есть два разных способа указать внешний инструмент сравнения.

Первый - это метод, который вы использовали, установив переменную GIT_EXTERNAL_DIFF. Однако предполагается, что переменная указывает на полный путь к исполняемому файлу. Кроме того, исполняемый файл, указанный в GIT_EXTERNAL_DIFF, будет вызываться с фиксированным набором из 7 аргументов:

path old-file old-hex old-mode new-file new-hex new-mode

Поскольку большинству инструментов сравнения потребуется другой порядок (и только некоторые) аргументов, вам, скорее всего, придется вместо этого указать скрипт-обертку, который, в свою очередь, вызывает настоящий инструмент сравнения.

Второй метод, который я предпочитаю, это настроить внешний инструмент сравнения через "git config". Вот что я сделал:

1) Создайте скрипт-обертку "git-diff-wrapper.sh", который содержит что-то вроде

-->8-(snip)--
#!/bin/sh

# diff is called by git with 7 parameters:
# path old-file old-hex old-mode new-file new-hex new-mode

"<path_to_diff_executable>" "$2" "$5" | cat
--8<-(snap)--

Как видите, только второй ("старый файл") и пятый ("новый файл") аргументы будут переданы в инструмент сравнения.

2) Тип

$ git config --global diff.external <path_to_wrapper_script>

в командной строке, заменив путь к "git-diff-wrapper.sh", поэтому ваш ~/.gitconfig содержит

-->8-(snip)--
[diff]
    external = <path_to_wrapper_script>
--8<-(snap)--

Обязательно используйте правильный синтаксис, чтобы указать пути к сценарию-оболочке и инструменту сравнения, т.е. Используйте прямую косую черту вместо обратной косой черты. В моем случае у меня есть

[diff]
    external = \"c:/Documents and Settings/sschuber/git-diff-wrapper.sh\"

в .gitconfig и

"d:/Program Files/Beyond Compare 3/BCompare.exe" "$2" "$5" | cat

в сценарии оболочки. Следите за "котом"!

(Я полагаю, что ' | cat ' требуется только для некоторых программ, которые могут не возвращать правильный или непротиворечивый статус возврата. Вы можете попробовать без завершающего cat, если ваш инструмент сравнения имеет явный статус возврата)

(Диомидис Спинеллис добавляет в комментариях:

Требуется команда cat, потому что diff(1) по умолчанию завершает работу с кодом ошибки, если файлы различаются.
Git ожидает, что внешняя программа сравнения завершит работу с кодом ошибки, только если произошла фактическая ошибка, например, если она исчерпала память.
Путем передачи вывода git в cat ненулевой код ошибки маскируется.
Более эффективно, программа может просто запустить exit с аргументом 0.)


Это (статья, приведенная выше) является теорией для внешнего инструмента, определенного через конфигурационный файл (не через переменную окружения).
На практике (все еще для определения файла конфигурации внешнего инструмента), вы можете обратиться к:

Ответ 2

Чтобы завершить мой предыдущий конфиг "diff.external", ответ выше:

Как упомянул Jakub, в Git1.6.3 появился git difftool, первоначально предложенный в сентябре 2008 года:

USAGE = '[--tool=tool] [--commit=ref] [--start=ref --end=ref] [--no-prompt] [file to merge]'
(См. --extcmd в последней части этого ответа)

$LOCAL содержит содержимое файла из начальной ревизии, а $REMOTE содержит содержимое файла в конечной ревизии.
$BASE содержит содержимое файла в мире

Это в основном git-mergetool модифицированный для работы с git index/worktree.

Обычный сценарий использования этого сценария - когда вы вносите или не ставите изменения, и вы хотите видеть изменения в параллельном средстве просмотра diff (например, xxdiff, tkdiff и т.д.).

git difftool [<filename>*]

Другой вариант использования - это когда вы хотели бы видеть ту же информацию, но сравнивать произвольные коммиты (это та часть, в которой анализ синтаксиса может быть лучше)

git difftool --start=HEAD^ --end=HEAD [-- <filename>*]

Последний вариант использования - это когда вы хотите сравнить текущее рабочее дерево с чем-то отличным от HEAD (например, тегом).

git difftool --commit=v1.0.0 [-- <filename>*]

Примечание: начиная с Git 2.5 достаточно git config diff.tool winmerge !
Смотрите " git mergetool winmerge "

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


Перед Git 2.5:

Практический пример настройки difftool с помощью вашего специального инструмента diff:

C:\myGitRepo>git config --global diff.tool winmerge
C:\myGitRepo>git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""
C:\myGitRepo>git config --global difftool.prompt false

С winmerge.sh, хранящимся в директории вашего PATH:

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

Если у вас есть другой инструмент (kdiff3, P4Diff,...), создайте другой сценарий оболочки и соответствующую директиву config difftool.myDiffTool.cmd.
Тогда вы можете легко переключать инструменты с diff.tool конфигурации diff.tool.

У вас также есть эта запись в блоге Дейва, чтобы добавить другие детали.
(Или этот вопрос для вариантов winmergeu)

Интерес к этому параметру представляет сценарий winmerge.sh: вы можете настроить его для учета особых случаев.

Смотрите, например, ответ Дэвида Мрамора ниже для примера, который имеет дело с:

  • новые файлы в исходном или целевом
  • удаленные файлы в исходном или целевом

Как упоминает Кем Мейсон в своем ответе, вы также можете избежать любой оболочки, используя --extcmd:

--extcmd=<command>

Укажите пользовательскую команду для просмотра различий. git-difftool игнорирует сконфигурированные значения по умолчанию и запускает $command $LOCAL $REMOTE когда указана эта опция.

Например, вот как gitk может запускать/использовать любой инструмент diff.

Ответ 3

В духе ответа на вопросы, которые несколько отличаются от заданных. Попробуйте это решение:

$ meld my_project_using_git

Meld понимает git и обеспечивает навигацию по недавним изменениям.

Ответ 4

Так как git версия 1.6.3 есть " git difftool", который вы можете настроить, чтобы использовать свой любимый инструмент графического разграничения. В настоящее время поддерживаются готовые приложения: kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, diffuse и opendiff; если инструмент, который вы хотите использовать, отсутствует в этом списке, вы всегда можете использовать параметр конфигурации < difftool.<tool>.cmd.

"git diffftool" принимает те же параметры, что и "git diff".

Ответ 5

С новым git difftool это так же просто, как добавить это в ваш файл .gitconfig:

[diff]
    tool = any-name
[difftool "any-name"]
    cmd = "\"C:/path/to/my/ext/diff.exe\" \"$LOCAL\" \"$REMOTE\""

При желании также добавьте:

[difftool]
    prompt = false

Также ознакомьтесь с diffall, простым сценарием, который я написал для расширения раздражающего (IMO) поведения diff по умолчанию при открытии каждого в сериале.

Глобальный .gitconfig в Windows находится в %USERPROFILE%\.gitconfig

Ответ 6

У меня есть одно дополнение к этому. Мне нравится регулярно использовать приложение diff, которое не поддерживается как один из стандартных инструментов (например, калейдоскоп), через

git difftool -t

Мне также нравится, что значение по умолчанию diff просто является обычной командной строкой, поэтому установка переменной GIT_EXTERNAL_DIFF не является параметром.

Вы можете использовать произвольное приложение diff как одноразовое с помощью этой команды:

git difftool --extcmd=/usr/bin/ksdiff

Он просто передает 2 файла в указанную вами команду, поэтому вам, вероятно, также не нужна оболочка.

Ответ 7

На основе ответа VonC для обработки удалений и дополнений файлов используйте следующие команды и скрипты:

> git config --global diff.tool winmerge
> git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\" \"$BASE\""
> git config --global difftool.prompt false

То же самое, что и в глобальном .gitconfig:

[diff]
    tool = winmerge
[difftool "winmerge"]
    cmd = winmerge.bat "$LOCAL" "$REMOTE" "$BASE"
[difftool]
    prompt = false

Затем добавьте следующее в winmerge.sh, которое должно быть на вашем пути:

#!/bin/sh
NULL="/dev/null"
if [ "$2" = "$NULL" ] ; then
    echo "removed: $3"
elif [ "$1" = "$NULL" ] ; then
    echo "added: $3"
else
    echo "changed: $3"
    "C:/Program Files (x86)/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$1" "$2"
fi

Ответ 8

Решение для Windows/msys git

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

  • Создайте командный файл для вызова вашей программы diff с аргументами 2 и 5. Этот файл должен быть где-то на вашем пути. (Если вы не знаете, где это, поместите его в c:\windows). Назовите его, например, "gitdiff.bat". Мой:

    @echo off
    REM This is gitdiff.bat
    "C:\Program Files\WinMerge\WinMergeU.exe" %2 %5
    
  • Установите переменную окружения для указания на пакетный файл. Например: GIT_EXTERNAL_DIFF=gitdiff.bat. Или через powershell, набрав git config --global diff.external gitdiff.bat.

    Важно не использовать кавычки или указывать любую информацию о пути, иначе это не сработает. Вот почему gitdiff.bat должен быть на вашем пути.

Теперь, когда вы набираете "git diff", он будет вызывать ваш внешний анализатор различий.

Ответ 9

Если вы делаете это через cygwin, вам может потребоваться использовать cygpath:

$ git config difftool.bc3.cmd "git-diff-bcomp-wrapper.sh \$LOCAL \$REMOTE"
$ cat git-diff-bcomp-wrapper.sh
#!/bin/sh
"c:/Program Files (x86)/Beyond Compare 3/BComp.exe" `cygpath -w $1` `cygpath -w $2`

Ответ 10

Посмотрев на некоторые другие внешние инструменты сравнения, я обнаружил, что представление diff в IntelliJ IDEA (и Android Studio) является лучшим для меня.

Шаг 1 - настроить IntelliJ IDEA для запуска из командной строки

Если вы хотите использовать IntelliJ IDEA в качестве инструмента дифф вы должны сначала настроить IntelliJ IDEA для запуска из командной строки, следуя инструкции здесь:

В macOS или UNIX:

  1. Убедитесь, что IntelliJ IDEA работает.
  2. В главном меню выберите Tools | Create Command-line Launcher Tools | Create Command-line Launcher. Откроется диалоговое окно "Создать сценарий запуска" с предложенным путем и именем сценария запуска. Вы можете принять значение по умолчанию или указать свой собственный путь. Обратите внимание на это, так как оно понадобится вам позже. Вне IntelliJ IDEA добавьте путь и имя сценария запуска к своему пути.

В Windows:

  1. Укажите местоположение исполняемого файла IntelliJ IDEA в системной переменной среды Path. В этом случае вы сможете вызывать исполняемый файл IntelliJ IDEA и другие команды IntelliJ IDEA из любого каталога.

Шаг 2 - настройте git для использования IntelliJ IDEA в качестве difftool

Следуя инструкциям в этом блоге:

удар

export INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS
PATH=$IDEA_HOME $PATH

Рыба

set INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS
set PATH $INTELLIJ_HOME $PATH

Теперь добавьте следующее в ваш git config:

[merge]
   tool = intellij
[mergetool "intellij"]
   cmd = idea merge $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE") $(cd $(dirname "$BASE") && pwd)/$(basename "$BASE") $(cd $(dirname "$MERGED") && pwd)/$(basename "$MERGED")
   trustExitCode = true
[diff]
   tool = intellij
[difftool "intellij"]
   cmd = idea diff $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE")

Вы можете попробовать это с помощью git difftool или git difftool HEAD~1

Ответ 11

это работает для меня на окнах 7. Нет необходимости в промежуточных сценариях

содержимое .gitconfig:

    [diff]
      tool = kdiff3

    [difftool]
       prompt = false

    [difftool "kdiff3"]
      path = C:/Program Files (x86)/KDiff3/kdiff3.exe
      cmd = "$LOCAL" "$REMOTE"

Ответ 12

Краткий обзор вышеупомянутых замечательных ответов:

git difftool --tool-help
git config --global diff.tool <chosen tool>
git config --global --add difftool.prompt false

Затем используйте его, набрав (необязательно указав имя файла):

git difftool

Ответ 13

Введение

Для справки я хотел бы включить мой вариант ответа VonC. Имейте в виду, что я использую версию MSys Git (1.6.0.2 в это время) с измененным PATH и запускаю Git из Powershell (или cmd.exe), а не в оболочку Bash.

Я ввел новую команду gitdiff. Выполнение этой команды временно перенаправляет git diff, чтобы использовать программу визуального разбора по вашему выбору (в отличие от решения VonC, которое делает это постоянно). Это позволяет мне иметь как функциональность по умолчанию Git diff (git diff), так и функциональность визуального разграничения (gitdiff). Обе команды принимают одинаковые параметры, поэтому, например, чтобы визуально различать изменения в конкретном файле, вы можете ввести

gitdiff path/file.txt

Настройка

Обратите внимание, что $GitInstall используется как местозаполнитель для каталога, в котором установлен Git.

  • Создайте новый файл $GitInstall\cmd\gitdiff.cmd

    @echo off
    setlocal
    for /F "delims=" %%I in ("%~dp0..") do @set path=%%~fI\bin;%%~fI\mingw\bin;%PATH%
    if "%HOME%"=="" @set HOME=%USERPROFILE%
    set GIT_EXTERNAL_DIFF=git-diff-visual.cmd
    set GIT_PAGER=cat
    git diff %*
    endlocal
    
  • Создайте новый файл $GitInstall\bin\git-diff-visual.cmd (заменив [visual_diff_exe] placeholder полным путем на программу diff по вашему выбору)

    @echo off
    rem diff is called by git with 7 parameters:
    rem path old-file old-hex old-mode new-file new-hex new-mode
    echo Diffing "%5"
    "[visual_diff_exe]" "%2" "%5"
    exit 0
    
  • Теперь вы закончили. Запуск gitdiff из репозитория Git должен теперь вызывать вашу программу визуального разграничения для каждого измененного файла.

Ответ 14

Здесь командный файл, который работает для Windows, предполагает, что DiffMerge установлен в местоположение по умолчанию, обрабатывает x64, обращается к замене обратной косой черты по мере необходимости и имеет возможность самостоятельно установить. Должно быть легко заменить DiffMerge на вашу любимую программу diff.

Для установки:

gitvdiff --install 

gitvdiff.bat:

@echo off

REM ---- Install? ----
REM To install, run gitvdiff --install

if %1==--install goto install



REM ---- Find DiffMerge ----

if DEFINED ProgramFiles^(x86^) (
    Set DIFF="%ProgramFiles(x86)%\SourceGear\DiffMerge\DiffMerge.exe"
) else (
    Set DIFF="%ProgramFiles%\SourceGear\DiffMerge\DiffMerge.exe"
)



REM ---- Switch forward slashes to back slashes ----

set oldW=%2
set oldW=%oldW:/=\%
set newW=%5
set newW=%newW:/=\%


REM ---- Launch DiffMerge ----

%DIFF% /title1="Old Version" %oldW% /title2="New Version" %newW%

goto :EOF



REM ---- Install ----
:install
set selfL=%~dpnx0
set selfL=%selfL:\=/%
@echo on
git config --global diff.external %selfL%
@echo off


:EOF

Ответ 15

Если вы находитесь на Mac и имеете XCode, то у вас установлен FileMerge. Команда терминала является opendiff, поэтому вы можете просто сделать git difftool -t opendiff

Ответ 16

Для версии Linux, как настроить инструмент diff в версиях git до 1.6.3 (1.6.3 добавлен diffftool до git) это - это отличный краткий учебник,

вкратце:

Шаг 1: добавьте это в свой .gitconfig

[diff]
  external = git_diff_wrapper
[pager]
  diff =

Шаг 2: создайте файл с именем git_diff_wrapper, поместите его где-нибудь в $PATH

#!/bin/sh

vimdiff "$2" "$5"

Ответ 17

Установить meld

 # apt-get install meld

Затем выберите это как diffftool

 $ git config --global diff.tool meld

Если tou хочет запустить его на консольном типе:

 $ git difftool

Если вы хотите использовать режим графического режима:

 $ git mergetool

И выход будет:

 'git mergetool' will now attempt to use one of the following tools:
 meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse
 diffmerge ecmerge p4merge araxis bc3 codecompare emerge vimdiff
 Merging:
 www/css/style.css
 www/js/controllers.js

 Normal merge conflict for 'www/css/style.css':
   {local}: modified file
   {remote}: modified file
 Hit return to start merge resolution tool (meld):

Итак, просто нажмите enter, чтобы использовать meld (по умолчанию), это откроет графический режим, сделайте волшебное сохранение и нажмите, что разрешит слияние. Что все

Ответ 18

В Mac OS X,

git difftool -t diffuse 

выполняет работу для меня в папке git. Для установки диффузного можно использовать порт -

sudo port install diffuse

Ответ 19

вы можете использовать git difftool.

например, если у вас meld, вы можете редактировать ветки master и devel с помощью:

git config --global diff.external meld
git difftool master..devel

Ответ 20

Я попробовал причудливые вещи здесь (с tkdiff), и ничто не помогло мне. Поэтому я написал следующий script, tkgitdiff. Он делает то, что мне нужно.

$ cat tkgitdiff
#!/bin/sh

#
# tkdiff for git.
# Gives you the diff between HEAD and the current state of your file.
#

newfile=$1
git diff HEAD -- $newfile > /tmp/patch.dat
cp $newfile /tmp
savedPWD=$PWD
cd /tmp
patch -R $newfile < patch.dat
cd $savedPWD
tkdiff /tmp/$newfile $newfile

Ответ 21

Следующее можно почерпнуть из других ответов здесь, но для меня это сложно (слишком много информации), поэтому здесь ответ "просто введите его" для tkdiff:

git difftool --tool=tkdiff <path to the file to be diffed>

Вы можете заменить имя исполняемого файла вашего любимого инструмента сравнения на tkdiff. Пока (например, tkdiff) (или ваш любимый инструмент сравнения) находится в вашем PATH, он будет запущен.

Ответ 22

Я использовал этот бит в ~/.gitconfig в течение длительного времени:

[diff]
    external = ~/Dropbox/source/bash/git-meld

С git-meld:

#!/bin/bash
if [ "$DISPLAY" = "" ];
then
    diff $2 $5
else
    meld $2 $5
fi

Но теперь мне надоело всегда использовать meld в графической среде, и это не тривиально, чтобы вызвать нормальный diff с этой настройкой, поэтому я переключился на это:

[alias]
    v =  "!sh -c 'if [ $# -eq 0 ] ; then git difftool -y -t meld ; else git difftool -y [email protected] ; fi' -"

С помощью этой настройки такие вещи, как эта работа:

git v
git v --staged
git v -t kompare
git v --staged -t tkdiff

И я до сих пор хочу сохранить старый добрый git diff.

Ответ 23

Я использую kompare на ubuntu:

sudo apt-get install kompare

Чтобы сравнить две ветки:

git difftool -t kompare <my_branch> master

Ответ 24

Вы можете попробовать xd http://github.com/jiqingtang/xd, который является оболочкой GUI для GIT/SVN diff. Это НЕ инструмент для анализа. Вы запускаете xd, когда хотите запустить git diff или svn diff, и он покажет вам список файлов, окно предварительного просмотра, и вы можете запустить любой инструмент, который вам нравится, включая tkdiff, xxdiff, gvimdiff, emacs (ediff), xemacs (ediff), meld, diffuse, kompare и kdiff3. Вы также можете запустить любой настраиваемый инструмент.

К сожалению, инструмент не поддерживает Windows.

Раскрытие. Я являюсь автором этого инструмента.

Ответ 25

Если у вас уже есть инструмент diff, связанный с файловыми типами (скажем, потому что вы установили TortoiseSVN, который поставляется с программой просмотра diff), вы можете просто отправить обычный git diff вывод в файл temp, а затем просто открыть это напрямую, без необходимости знать что-либо о зрителе:

git diff > "~/temp.diff" && start "~/temp.diff"

Настройка его как глобального псевдонима работает еще лучше: git what

[alias]
    what = "!f() { git diff > "~/temp.diff" && start "~/temp.diff"; }; f"

Ответ 26

Если вы не являетесь одной из командной строки, то, если вы устанавливаете черепаху git, вы можете щелкнуть правой кнопкой мыши файл, чтобы получить подменю tortoisegit с опцией "Diff later".

Когда вы выбираете это в первом файле, вы можете щелкнуть правой кнопкой мыши по второму файлу, перейдите в подменю tortoisegit и выберите "Diff with == yourfilehere ==", Это даст результат черепах.