Git diff фильтруется по имени файла

Я хотел бы, чтобы результаты git diff были отфильтрованы по имени файла.

В частности, мне нужен diff для всех файлов с именем "AssemblyInfo.cs", но расположенных где-нибудь в репозитории git.

Я использую git для Cygwin, если это имеет значение.

Ответ 1

Аргументы файла для git diff должны быть разделены символом -- - попробуйте следующее:

find . -name <pattern> | xargs git diff --

xargs позволяет корректно обрабатывать пробелы, табуляции, новые строки и т.д.

Вы можете отладить его с аргументом --name-status до git diff. Вы также можете попробовать:

git diff --name-only | grep <pattern>

[edit] Попробуйте:

git diff --name-status -- `find . -name '<pattern>'`
[email protected](98)$ git diff --name-status -- `find . -name '*.scm'`
M       scheme/base/boolean.scm
M       surf/compiler/common.scm
M       surf/compiler/compile.scm
M       surf/compiler/expand.scm

Ответ 2

Самый простой способ - просто использовать подстановочный знак:

git diff -- '*AssemblyInfo.cs'


По крайней мере, это работает на моем Git v1.8.4, bash 3.2 и zsh 5.7.

Ответ 3

Вы можете использовать pipeline

find . -name AssemblyInfo.cs | git diff

Используйте find для фильтрации всех файлов с именем "AssemblyInfo.cs", затем используйте вывод в качестве параметра git diff.

Ответ 4

В то время как ответ, заданный GoZoner, работает для некоторых (сотни?) файлов, он выполняет git diff несколько раз (в случае xargs) или не работает (в случае git diff … -- `find …`), если для diff существует большое количество файлов. Это может быть проблемой или нет, в зависимости от вашего варианта использования.

Возможное решение состоит в создании коммита, содержащего только изменения в интересующих файлах и diff commit. Основываясь на ответе на неподходящие файлы, соответствующие некоторому шаблону, я придумал это решение:

git co <new_branch> --detach
git reset --soft <old_branch>

Теперь git status --porcelain | grep <pattern> отображает все файлы, которые нужно сравнить. Все остальные файлы можно перечислить, передав -v в grep, т.е. git status --porcelain | grep -v <pattern>. Эти файлы должны быть reset для состояния <old_branch>:

# Remove the destination of renamed and copied files not matching <pattern>
git status --porcelain | grep -v <pattern> | grep '^R \|^C ' | sed 's/.* -> //' | xargs git rm -f --
# Remove added files not matching <pattern>
git status --porcelain | grep -v <pattern> | grep '^A ' | cut -c 4- | xargs git rm -f --
# Restore deleted files not matching <pattern>
git status --porcelain | grep -v <pattern> | grep '^M \|^D ' | cut -c 4- | xargs git checkout HEAD --

(Обратите внимание, что использование xargs не является проблемой в этом случае, поскольку вызов git rm и git checkout несколько раз в порядке.)

Теперь индекс (и рабочая копия) содержит только изменения в файлах, соответствующих <pattern>. Следующее, что нужно сделать, это выполнить следующие изменения:

git commit -m "Changes between <old_branch> and <new_branch> in files matching <pattern>"

Что это! Теперь мы можем использовать git diff, как обычно:

git diff HEAD^..HEAD

Вы можете использовать все параметры или аргументы, которые вам нравятся.

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

Ответ 5

find . -iregex AssemblyInfo\.cs -exec git diff {} +

вы можете заменить AssemblyInfo\.cs своим регулярным выражением.

Ответ 6

Вероятно, самый простой вариант - использовать:

git diff "*/*AssemlyInfo.cs"

работает с git 2.20.1