我正在尝试生成在特定提交中更改的文件列表。问题是,每个文件在文件顶部的注释中都有版本号 - 并且由于此提交引入了新版本,这意味着每个文件都已更改。
我不关心更改的注释,所以我想让git diff忽略所有匹配^\s*\*.*$
的行,因为这些都是注释(/ * * /的一部分)。
我找不到任何方法来告诉git diff忽略特定的行。
我已经尝试过设置一个textconv属性,让git在传播文件之前将文件传递给sed,这样sed就可以删除有问题的行 - 这个问题就是git diff --name-status没有实际上是差异文件,只是比较哈希值,当然所有哈希值都已经改变了。
有没有办法做到这一点?
答案 0 :(得分:11)
这是一个适合我的解决方案。我已经在git (log|diff) -G<regex>
选项上写了解决方案和一些其他缺少的文档。
基本上使用与上述相同的解决方案,但专门针对以*
或#
开头的评论,有时候是*
之前的空格......但仍需要允许#ifdef
,#include
等更改。
向前看并向后看似乎-G
选项似乎不支持,?
也不支持,我也遇到了使用*
的问题。 +
似乎运作良好。
(注意,在Git v2.7.0上测试)
git diff -w -G'(^[^\*# /])|(^#\w)|(^\s+[^\*#/])'
-w
忽略空格-G
仅显示与以下正则表达式匹配的差异线(^[^\*# /])
任何不以星号或散列或空格开头的行(^#\w)
任何以#
开头,后跟字母(^\s+[^\*#/])
任何以空格开头后跟注释字符基本上,svn挂钩会立即修改每个文件,并修改每个文件上的多行注释块。现在,我可以根据svn在评论中删除的fyi信息来区分我对svn的更改。
从技术上讲,这将允许在diff中显示像#TODO
这样的python和bash注释,如果在c ++中使用除法运算符在新行上启动,则可以忽略它:
a = b
/ c;
git中-G
的文档似乎也很缺乏,所以这里的信息应该会有所帮助:
git diff -G<regex>
<强>
-G<regex>
强>查找其修补程序文本包含与
<regex>
匹配的添加/删除行的差异。为了说明
-S<regex> --pickaxe-regex
和-G<regex>
之间的区别,
考虑在同一个文件中使用以下差异进行提交:+ 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)中的 pickaxe 条目。
(注意,在Git v2.7.0上测试)
-G
使用基本的正则表达式。?
,*
,!
,{
,}
正则表达式语法。()
和OR-ing组进行分组可以使用|
。\s
,\W
等通配符字符。^$
工作。请注意,-G
选项会过滤要分散的文件。
但是如果一个文件被“分散”,那么“ all 之前被”排除/包含“的那些行将在差异中显示。
仅显示至少有一行提及foo
的文件差异。
git diff -G'foo'
显示除以#
git diff -G'^[^#]'
显示提及FIXME
或TODO
git diff -G`(FIXME)|(TODO)`
另请参阅git log -G
,git grep
,git log -S
,--pickaxe-regex
,--pickaxe-all
https://github.com/git/git/search?utf8=%E2%9C%93&q=regcomp&type=
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
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.
希望能帮到每个人。
答案 1 :(得分:7)
git diff -G <regex>
并指定与版本号行不匹配的正则表达式。
答案 2 :(得分:6)
我发现使用git difftool
启动外部差异最简单:
git difftool -y -x "diff -I '<regex>'"
答案 3 :(得分:2)
找到解决方案。我可以使用这个命令:
git diff --numstat --minimal <commit> <commit> | sed '/^[1-]\s\+[1-]\s\+.*/d'
显示提交之间更改了1行以上的文件,这样可以删除仅更改为注释中版本号的文件。
答案 4 :(得分:0)
也许这样的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
答案 5 :(得分:0)
在'git diff'输出中使用'grep':
git diff -w | grep -c -E "(^[+-]\s*(\/)?\*)|(^[+-]\s*\/\/)"
单独评论行更改可以计算。 (A)
使用'git diff --stat'输出:
git diff -w --stat
可以计算所有行变化。 (B)
获取非注释源行更改(NCSL)计数,从(B)中减去(A)。
说明: 在'git diff'输出中(忽略空格更改),
注意:由于以下假设,评论行数可能会出现轻微错误,结果应视为大概数字。
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);
答案 6 :(得分:0)
对于大多数语言,要正确执行此操作,您必须解析原始源文件/ ast,并以这种方式排除注释。
一个原因是,差异可能不会涵盖多行注释的开头。另一个原因是,语言解析并不是一件容易的事,并且常常有一些事情可能会使幼稚的解析器崩溃。
我打算为python做到这一点,但是字符串黑客足以满足我的需求。
对于python,您可以使用自定义过滤器忽略注释和尝试忽略文档字符串,例如:
https://gist.github.com/earonesty/f76dec337ee64c5ae23c2be1557535a4
可以简单地修改该代码以产生文件名,而不是计数。
但是,它当然可以错误地将文档字符串的一部分计为“代码”(不适用于诸如覆盖率等内容)。