如何让 git diff 忽略注释
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16527215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make git diff ignore comments
提问by Benubird
I am trying to produce a list of the files that were changed in a specific commit. The problem is, that every file has the version number in a comment at the top of the file - and since this commit introduces a new version, that means that every file has changed.
我正在尝试生成在特定提交中更改的文件列表。问题是,每个文件在文件顶部的注释中都有版本号 - 由于此提交引入了新版本,这意味着每个文件都已更改。
I don't care about the changed comments, so I would like to have git diff ignore all lines that match ^\s*\*.*$
, as these are all comments (part of /* */).
我不关心更改的注释,所以我想让 git diff 忽略所有匹配的行^\s*\*.*$
,因为这些都是注释(/* */ 的一部分)。
I cannot find any way to tell git diff to ignore specific lines.
我找不到任何方法来告诉 git diff 忽略特定行。
I have already tried setting a textconv attribute to cause git to pass the files to sed before diffing them, so that sed can strip out the offending lines - the problem with this, is that git diff --name-status does not actually diff the files, just compares the hashes, and of course all the hashes have changed.
我已经尝试设置一个 textconv 属性,使 git 在比较它们之前将文件传递给 sed,这样 sed 就可以去掉有问题的行 - 问题在于 git diff --name-status 实际上并没有区分文件,只是比较散列,当然所有的散列都改变了。
Is there any way to do this?
有没有办法做到这一点?
采纳答案by riezebosch
git diff -G <regex>
And specify a regex that does NOT match your version number line.
并指定一个与您的版本号行不匹配的正则表达式。
回答by phyatt
Here is a solution that is working well for me. I've written up the solution and some additional missing documentation on the git (log|diff) -G<regex>
option.
这是一个对我来说效果很好的解决方案。我已经编写了解决方案和有关该git (log|diff) -G<regex>
选项的一些其他缺失文档。
Basically using the same solution as above, but specifically for comments that start with a *
or a #
, and sometimes a space before the *
... But it still needs to allow #ifdef
, #include
, etc changes.
基本上使用相同的解决方案如上,但是专门为以a开头的评论*
或#
之前的,有时候一个空间*
......但它仍然需要允许#ifdef
,#include
等变化。
Look ahead and look behind do not seem to be supported by the -G
option, nor does the ?
in general, and I have had problems with using *
, too. +
seems to be working well, though.
该-G
选项似乎不支持向前看和向后看?
,一般情况下也不支持,而且我在使用*
时也遇到了问题。 +
不过,似乎运作良好。
(note, tested on Git v2.7.0)
(注意,在 Git v2.7.0 上测试过)
Multi-Line Comment Version
多行注释版
git diff -w -G'(^[^\*# /])|(^#\w)|(^\s+[^\*#/])'
-w
ignore whitespace-G
only show diff lines that match the following regex(^[^\*# /])
any line that does not start with a star or a hash or a space(^#\w)
any line that starts with#
followed by a letter(^\s+[^\*#/])
any line that starts with some whitespace followed by a comment character
-w
忽略空格-G
仅显示与以下正则表达式匹配的差异行(^[^\*# /])
任何不以星号、散列或空格开头的行(^#\w)
任何以开头#
后跟一个字母的行(^\s+[^\*#/])
任何以空格开头后跟注释字符的行
Basically an svn hook modifies every file in and out right now and modifies multi-line comment blocks on every file. Now I can diff my changes against svn without the fyi info that svn drops in the comments.
基本上 svn 钩子现在修改每个文件的进出,并修改每个文件上的多行注释块。现在我可以将我的更改与 svn 进行比较,而无需 svn 在评论中删除的 fyi 信息。
Technically this will allow for python and bash comments like #TODO
to be shown in the diff, and if a division operator started on a new line in c++ it could be ignored:
从技术上讲,这将允许#TODO
在差异中显示python 和 bash 注释,如果除法运算符在 c++ 中的新行开始,则可以忽略它:
a = b
/ c;
Also the documentation on -G
in git seemed pretty lacking, so the info here should help:
此外,关于-G
git的文档似乎非常缺乏,所以这里的信息应该会有所帮助:
git diff -G<regex>
git diff -G<regex>
-G<regex>
Look for differences whose patch text contains added/removed lines that match
<regex>
.To illustrate the difference between
-S<regex> --pickaxe-regex
and-G<regex>
,
consider a commit with the following diff in the same file:+ return !regexec(regexp, two->ptr, 1, ®match, 0); ... - hit = !regexec(regexp, mf2.ptr, 1, ®match, 0);
While
git log -G"regexec\(regexp"
will show this commit,git log -S"regexec\(regexp" --pickaxe-regex
will not
(because the number of occurrences of that string did not change).See the pickaxeentry in gitdiffcore(7)for more information.
-G<regex>
查找补丁文本包含匹配的添加/删除行的差异
<regex>
。为了说明之间的区别
-S<regex> --pickaxe-regex
和-G<regex>
,
考虑在同一个文件中的以下DIFF提交:+ return !regexec(regexp, two->ptr, 1, ®match, 0); ... - hit = !regexec(regexp, mf2.ptr, 1, ®match, 0);
虽然
git log -G"regexec\(regexp"
会显示此提交,但git log -S"regexec\(regexp" --pickaxe-regex
不会
(因为该字符串的出现次数没有改变)。有关更多信息,请参阅gitdiffcore(7) 中的镐条目。
(note, tested on Git v2.7.0)
(注意,在 Git v2.7.0 上测试过)
-G
uses basic regex.- No support for
?
,*
,!
,{
,}
regex syntax. - Grouping with
()
and OR-ing groups works with|
. - Wild card characters such as
\s
,\W
, etc are supported. - Look-ahead and look-behind are notsupported.
- Beginning and ending line anchors
^$
work. - Feature has been available since Git 1.7.4.
-G
使用基本的正则表达式。- 不支持
?
,*
,!
,{
,}
正则表达式语法。 - 分组
()
和 OR-ing 组与|
. - 通配符如
\s
,\W
等的支持。 - 不支持前瞻和后视。
- 开始和结束线锚点
^$
工作。 - 该功能从 Git 1.7.4 开始可用。
Excluded Files v Excluded Diffs
排除的文件 v 排除的差异
Note that the -G
option filters the files that will be diffed.
请注意,该-G
选项会过滤将被区分的文件。
But if a file gets "diffed" those lines that were "excluded/included" before will allbe shown in the diff.
但是,如果文件被“差异化”,之前“排除/包含”的那些行将全部显示在差异中。
Examples
例子
Only show file differences with at least one line that mentions foo
.
仅显示至少有一行提到的文件差异foo
。
git diff -G'foo'
Show file differences for everything except lines that start with a #
显示除以 a 开头的行之外的所有内容的文件差异 #
git diff -G'^[^#]'
Show files that have differences mentioning FIXME
or TODO
显示有差异的文件提及FIXME
或TODO
git diff -G`(FIXME)|(TODO)`
See also git log -G
, git grep
, git log -S
, --pickaxe-regex
, --pickaxe-all
另见git log -G
, git grep
, git log -S
, --pickaxe-regex
,--pickaxe-all
UPDATE: Which regex tool is in use by the -G option?
更新: -G 选项正在使用哪个正则表达式工具?
https://github.com/git/git/search?utf8=%E2%9C%93&q=regcomp&type=
https://github.com/git/git/search?utf8=%E2%9C%93&q=regcomp&type=
https://github.com/git/git/blob/master/diffcore-pickaxe.c
https://github.com/git/git/blob/master/diffcore-pickaxe.c
if (opts & (DIFF_PICKAXE_REGEX | DIFF_PICKAXE_KIND_G)) {
int cflags = REG_EXTENDED | REG_NEWLINE;
if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
cflags |= REG_ICASE;
regcomp_or_die(®ex, needle, cflags);
regexp = ®ex;
// and in the regcom_or_die function
regcomp(regex, needle, cflags);
http://man7.org/linux/man-pages/man3/regexec.3.html
http://man7.org/linux/man-pages/man3/regexec.3.html
REG_EXTENDED
Use POSIX Extended Regular Expression syntax when interpreting
regex. If not set, POSIX Basic Regular Expression syntax is
used.
// ...
// ...
REG_NEWLINE
Match-any-character operators don't match a newline.
A nonmatching list ([^...]) not containing a newline does not
match a newline.
Match-beginning-of-line operator (^) matches the empty string
immediately after a newline, regardless of whether eflags, the
execution flags of regexec(), contains REG_NOTBOL.
Match-end-of-line operator ($) matches the empty string
immediately before a newline, regardless of whether eflags
contains REG_NOTEOL.
Hope that helps everyone.
希望对大家有帮助。
回答by richvdh
I found it easiest to use git difftool
to launch an external diff:
我发现它最容易用于git difftool
启动外部差异:
git difftool -y -x "diff -I '<regex>'"
回答by Benubird
Found a solution. I can use this command:
找到了解决办法。我可以使用这个命令:
git diff --numstat --minimal <commit> <commit> | sed '/^[1-]\s\+[1-]\s\+.*/d'
To show the files that have more than 1 line changed between commits, which eliminates files whose only change was the version number in the comments.
显示在提交之间更改超过 1 行的文件,这消除了唯一更改是注释中的版本号的文件。
回答by Saravanan Palanisamy
Using 'grep' on the 'git diff' output:
在 'git diff' 输出上使用 'grep':
git diff -w | grep -c -E "(^[+-]\s*(\/)?\*)|(^[+-]\s*\/\/)"
comment line changes alone can be calculated. (A)
可以单独计算注释行更改。(一种)
Using 'git diff --stat' output:
使用 'git diff --stat' 输出:
git diff -w --stat
all line changes can be calculated. (B)
可以计算所有线路变化。(乙)
To get Non Comment Source Line changes (NCSL) count, subtract (A) from (B).
要获得非注释源行更改 (NCSL) 计数,请从 (B) 中减去 (A)。
Explanation :In the 'git diff ' output (in which whitespace changes are ignored),
说明:在“git diff”输出中(其中空白更改被忽略),
- Look out for a line which start with either '+' or '-', which means modified line.
- There can be optional white-space characters following this. '\s*'
- Then look for comment line pattern '/*' (or) just '*' (or) '//'.
- Since, '-c' option is given with grep, just print the count. Remove '-c' option to see the comments alone in the diffs.
- 请注意以“+”或“-”开头的行,这意味着修改后的行。
- 在此之后可以有可选的空白字符。'\s*'
- 然后查找注释行模式“/*”(或)只是“*”(或)“//”。
- 因为,'-c' 选项是用 grep 给出的,所以只打印计数。删除“-c”选项以单独查看差异中的注释。
NOTE:There can be minor errors in the comment line count due to following assumptions, and the result should be taken as ballpark figure.
注意:由于以下假设,注释行数可能存在小错误,结果应视为大致数字。
1.) Source files are based on C language. Makefile, Shell script files have different convention '#' to denote the comment lines and if they are part of diffset, there comment lines won't be counted.
2.) GIT convention of line change: If a line is modified, GIT sees it as that particular line is deleted and a new line is inserted there and it may look like 2 lines are changed whereas in reality one line is modified.
In the below example, new definition of 'FOO' looks like two line change.
$ git diff --stat -w abc.h
...
-#define FOO 7
+#define FOO 105
...
1 files changed, 1 insertions(+), 1 deletions(-)
$3.) Valid comment lines not matching the pattern (or) Valid source code lines matching the pattern can cause errors in the calculation.
In the below example, "+ blah blah" line which doesn't start with '*' won't be detected as a comment line.
+ /* + blah blah + * + */
In the below example, "+ *ptr" line will be counted as comment line as it starts with *, though it is a valid source code line.
+ printf("\n %p", + *ptr);
1.) 源文件基于 C 语言。Makefile、Shell 脚本文件有不同的约定“#”来表示注释行,如果它们是 diffset 的一部分,则不会计算注释行。
2.) GIT 换行约定:如果修改了一行,GIT 会将其视为该特定行被删除并在那里插入新行,看起来可能更改了 2 行,而实际上修改了一行。
在下面的例子中,'FOO' 的新定义看起来像两行变化。
$ git diff --stat -w abc.h
...
-#define FOO 7
+#define FOO 105
...
1 个文件更改,1 个插入(+),1 个删除(-)
$3.) 与模式不匹配的有效注释行(或)与模式匹配的有效源代码行会导致计算错误。
在下面的示例中,不以“*”开头的“+ blah blah”行不会被检测为注释行。
+ /* + blah blah + * + */
在下面的示例中,“+ *ptr”行将被视为注释行,因为它以 * 开头,尽管它是一个有效的源代码行。
+ printf("\n %p", + *ptr);
回答by saeedgnu
Perhaps a bash script like this (I didn't test the code, let me know if you could make it work or not)
也许是这样的 bash 脚本(我没有测试代码,让我知道你是否可以使它工作)
#!/bin/bash
git diff --name-only "$@" | while read FPATH ; do
LINES_COUNT=`git diff --textconv "$FPATH" "$@" | sed '/^[1-]\s\+[1-]\s\+.*/d' | wc -l`
if [ $LINES_COUNT -gt 0 ] ; then
echo -e "$LINES_COUNT\t$FPATH"
fi
done | sort -n