У меня та же проблема, и придумал псевдоним, который сделал трюк (я использую Git 2.8.3)
[alias]
difftoolr = "!git difftool \"[email protected]\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
Как использовать:
difftoolr commit1..commit2 -M
(см в нижней части для большего количества примеров)
Как это работает:
Представьте, что у вас есть три файла, которые были переименованы. Один из них фактически изменил свой контент (поэтому вы хотите изучить его с помощью вашего diffftool), но остальные два идентичны, за исключением пути или имени (и вы хотите их игнорировать).
(different) path/file.old -> newPath/file.new
(identical) path/fileB.old -> newPath/fileB.new
(identical) path/fileC.old -> newPath/fileC.new
Что псевдоним делает генерирует путь спецификации, которые явно исключают fileB
и fileC
, то есть те файлы, которые, несмотря на переименование имеют содержание неизменным.
Другими словами, мы генерируем эти filespecs:
-- . :(exclude)path/fileB.old :(exclude)newPath/fileB.new :(exclude)path/fileC.old :(exclude)newPath/fileC.new
Обратите внимание (возможно, хитрая) часть: старый путь к файлу и новый путь к файлу должен быть как явно исключены.
Чтобы сделать это, мы выдаем git diff
со следующими директивами:
-M100%
: следовать переименовывает. Это означает, что git предполагает, что какое-то переименование было выполнено, и будет учитывать эту информацию, чтобы делать попарные сравнения. Порог - 100%, который дает указание git рассмотреть переименование тех файлов, которые имеют точно такой же контент, но не те, которые были изменены.
--diff-filter=R
: укажите только файлы, которые git считает переименованными, опустите остальные.
--names-only
: просто введите имена файлов, нет другой информации
-R
: Обратный. В одном фрагменте скрипта мы заменяем порядок сравнения (вроде переключения левой и правой сторон), поэтому он также выводит старые имена файлов. Например, директива -R
перечисляет файл newPath/fileB.new
как path/fileB.old
.
...sed...
: и, наконец, мы добавим директиву исключения :(exclude)
в начало всех имен файлов.
Чтобы справиться с другими делами, я создал три разных псевдонима (не очень элегантный, я бы хотел что-то более гибкое), чтобы его можно было использовать для указания различных видов сравнения.
git difftoolr0 -M
git difftoolr1 HEAD~1..HEAD -M
git difftoolr2 HEAD --cached -M
Во всех случаях «стороны сравнений» (коммитов, --cached или любой другой) должен быть указан в качестве первого параметра (ов). Например, git difftoolr2 -M HEAD --cached
не будет работать (потому что на первом месте находится -M
).
[alias]
# takes no parameter: sample usage: git difftoolr0 -M
difftoolr0 = "!git difftool \"[email protected]\" -- . $((git diff -M100% --diff-filter=R --name-only & git diff -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
# takes 1 parameter in first position: sample usage: git difftoolr1 HEAD~1..HEAD -M
difftoolr1 = "!git difftool \"[email protected]\" -- . $((git diff \"$1\" -M100% --diff-filter=R --name-only & git diff \"$1\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
# takes 2 parameters in first positions: sample usage: git difftoolr2 HEAD --cached -M
difftoolr2 = "!git difftool \"[email protected]\" -- . $((git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only & git diff \"$1\" \"$2\" -M100% --diff-filter=R --name-only -R) | sed 's/\\(.*\\)/:(exclude)\\1/g') #"
И, наконец, BeyondCompare может удовлетворить ваши потребности (и мое).
Он легко позволяет переключать бок о бок diff в «неструктурированный» diff.
Последний удаляет папки и оставляет только имена. Если имя файла совпадает (но пути могут отличаться), они считаются двумя версиями одного и того же файла (например, path/file.png
и newPath/file.png
). В этом случае, если содержимое не изменилось, их можно легко пропустить с помощью кнопки на верхней панели.
В случае возникновения конфликтов имен (несколько файлов на одной стороне сравнения имеют одно и то же имя под разными путями), он будет выбирать только один из них для сравнения и игнорировать остальные.