2013-03-15 89 views
7

我希望git diff的结果可以按文件名过滤。通过文件名筛选的git diff

特别是,我想为所有名为“AssemblyInfo.cs”的文件比较diff,但它位于git存储库中的任何位置。

我在Cygwin上使用git,如果这有所作为。

回答

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 2013-03-15 18:25:37

+0

也许最后一个文件没有改变。请根据我的建议进行调试。如果还不清楚,请在原始问题中发布我的调试建议的输出。 – GoZoner 2013-03-15 18:31:33

+0

'git diff --name-only | grep AssemblyInfo.cs'确实提供了正确的文件名,正如我所料,但我需要全差分输出。两个'找到。名称AssemblyInfo.cs | xargs git diff --'和'find。名称AssemblyInfo.cs | xargs git diff --name-status --'给出的文件不是“AssemblyInfo.cs”(如.sql文件)。 – Zantier 2013-03-19 09:36:50

0

您可以使用pipeline

find . -name AssemblyInfo.cs | git diff 

使用find过滤所有名为“的AssemblyInfo.cs”的文件,然后使用输出为git diff参数。

+1

这似乎并没有过滤差异。我做了线计数只是为了检查: '$ git diff | wc -l $ find。名称AssemblyInfo.cs | git diff | wc -l 1110' – Zantier 2013-03-15 18:03:42

+0

@Zantier find的输出是什么。名称AssemblyInfo.cs'? – pktangyue 2013-03-15 18:05:02

+0

'发现。名称AssemblyInfo.cs工作正常,给所有“AssemblyInfo.cs”文件提供路径。 – Zantier 2013-03-15 18:06:02

0

虽然the answer given by GoZoner作品一些(?百)文件,它执行git diff多次(在xargs的情况下)或失败(在git diff … -- `find …`的情况下)如果有大量文件需要比较。根据您的使用情况,这可能是个问题或不是问题。

一个可能的解决方案是创建一个只包含对感兴趣文件的更改并区分提交的提交。基于an answer on unstaging files matching some pattern我想出了这个解决方案:

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

现在git status --porcelain | grep <pattern>表明,应该比较的所有文件。所有其他文件可以通过传递-vgrep,即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 rmgit 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 v1.8.4。

+0

你不能通过这样的路径来限制 – user1133275 2015-11-05 21:02:13

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

你可以用你的正则表达式替换AssemblyInfo\.cs