2016-02-12 7 views
6

Я использую:мерзавец дифф переименование/перемещение и измененные файлы, но скип переименование/перемещение и одинаковые файлы

git diff HEAD --diff-filter=R -M 

с MELD внешним инструментом дифф, чтобы показать файлы, которые были как переименование/перемещение и измененными. Я всегда делаю git diff, прежде чем совершать фиксацию, чтобы проверить мою работу и правильно собрать сообщение фиксации. Часто я переименую/перемещаю файлы, которые также потребуют некоторых изменений пути в файлах, которые ссылаются на некоторые переименованные/перемещенные файлы.

Моя проблема заключается в том, что для того, чтобы показать diff файла, который был переименован, а затем изменен, git diff также выдает кучу meld-окон для файлов, которые были переименованы, но не изменены. Это может быть очень раздражающим. Как получить git diff для пропуска переименованных, но не измененных файлов? Я собираюсь увидеть все эти файлы, перечисленные как переименованные/перемещенные, когда я набираю git-статус намного более чистым способом, поэтому мне не нужны всплывающие окна для идентичных файлов с git diff.

ответ

1

У меня та же проблема, и придумал псевдоним, который сделал трюк (я использую 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). В этом случае, если содержимое не изменилось, их можно легко пропустить с помощью кнопки на верхней панели.

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