2013-03-15 2 views
7

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

В частности, мне нужен diff для всех файлов с именем «AssemblyInfo.cs», но расположен в любом месте в репозитории git.

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

ответ

9

файла аргументы git diff должны быть разграничены -- - попробуйте это:

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

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

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

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

[править] Попытка:

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 
+0

Это похоже на то, что просто 'git diff', но не содержит последний файл. – Zantier

+0

Возможно, последний файл не изменился. Пожалуйста, отлаживайте мои предложения выше. Если все еще неясно, опубликуйте результаты моих отладочных предложений в исходном вопросе. – GoZoner

+0

'git diff - только имя-только | grep AssemblyInfo.cs' действительно дает правильные имена файлов, как и следовало ожидать, но мне нужен полный вывод diff. Оба «находят». -name AssemblyInfo.cs | xargs git diff - 'и' find. -name AssemblyInfo.cs | xargs git diff --name-status - 'предоставляют файлы, которые не являются« AssemblyInfo.cs »(например, файлы .sql). – Zantier

0

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

find . -name AssemblyInfo.cs | git diff 

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

+1

Это не похоже на фильтрацию diff. Я сделал подсчет строк только для проверки: '$ git diff | wc -l $ найти. -name AssemblyInfo.cs | git diff | wc -l 1110' – Zantier

+0

@ Zantier, что является результатом 'find. -name AssemblyInfo.cs'? – pktangyue

+0

'найти. -name AssemblyInfo.cs' работает правильно, предоставляя пути ко всем файлам «AssemblyInfo.cs». – Zantier

0

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

Возможным решением является создание коммита, содержащего только изменения в интересующих файлах и diff commit. На основании an answer on unstaging files matching some pattern я пришел с этим решением:

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

Теперь git status --porcelain | grep <pattern> показывает все файлы, которые должны быть сопоставлены. Все остальные файлы могут быть перечислены путем передачи -v в grep, то есть git status --porcelain | grep -v <pattern>. Эти файлы должны быть сброшены в состояние <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 

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

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

1

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

git diff -- *AssemblyInfo.cs 


По крайней мере, это работает на моем Git версии 1.8.4.

+0

вы не можете ограничивать путь таким образом – user1133275

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

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