【问题标题】:ignoring changes matching a string in git diff忽略与 git diff 中的字符串匹配的更改
【发布时间】:2013-04-08 12:06:20
【问题描述】:

我对 git 中受版本控制的大量文件进行了一次简单的更改,我希望能够检查是否没有其他更改滑入这个大型提交中。

变化都是形式

-                       "main()",
+                       OOMPH_CURRENT_FUNCTION,

其中“main()”可以是任何函数的名称。我想生成所有不属于这种形式的更改的差异。

git diff 的 -G 和 -S 选项非常接近——它们发现确实匹配字符串或正则表达式的更改。

有什么好办法吗?

目前的尝试

另一个question 描述了如何否定正则表达式,使用这种方法我认为命令应该是

git diff -G '^((?!OOMPH_CURRENT_FUNCTION).)*$'

但这只是返回错误消息

fatal: invalid log-grep regex: Invalid preceding regular expression

所以我猜 git 不支持这个正则表达式功能。

我还注意到标准的 unix diff 具有 -I 选项来“忽略行都匹配 RE 的更改”。但是我找不到用unix diff工具替换git自己的diff的正确方法。

【问题讨论】:

  • 如果您能找到所有匹配的更改,请将它们存储在一个文件中并git diff | fgrep -vxf file
  • 也许您也可以将 git diff 的结果存储在一个文件中,并使用更好的正则表达式工具。
  • @tripleee 这行得通,谢谢!这不是一个理想的解决方案,但如果您将其重写为答案,我会接受。
  • @Loamhoof 我想到了这一点,但我认为您需要正确解析 diff 输出才能删除整个更改(而不仅仅是删除单行)。
  • 这完全值得一个功能请求......

标签: regex git diff


【解决方案1】:

尝试以下方法:

$ git diff > full_diff.txt
$ git diff -G "your pattern" > matching_diff.txt

然后您可以像这样比较两者:

$ diff matching_diff.txt full_diff.txt

如果所有更改都与模式匹配,full_diff.txtmatching_diff.txt 将相同,最后一个 diff 命令将不会返回任何内容。

如果有与模式不匹配的更改,最后一个diff 将突出显示这些。


您可以结合上述所有步骤,避免像这样创建两个额外的文件:

diff <(git diff -G "your pattern") <(git diff)  # works with other diff tools too

【讨论】:

  • 这行得通,而且我看不到任何明显的问题(除了奇怪的输出格式),所以我接受了。谢谢!我仍然认为应该有更好的方法来做到这一点。
  • 聪明。这正是我喜欢给我的工具集(vim)的那种解决方案。如果git-diff 增加一个否定的-G 选项来模仿GNU diff 的-x 的工作原理,那就更好了... :)
  • -G 匹配整个文件,而不仅仅是更改的部分。这意味着文件中包含您不需要的更改的任何其他更改都将被忽略。
【解决方案2】:

不再需要 grep!

在 Git 2.30(2021 年第一季度)中,“git diff(man) 系列命令学会了“-I&lt;regex&gt;”选项来忽略那些更改的行都匹配给定的模式。

参见Michał Kępień (kempniu)commit 296d4a9commit ec7967c(2020 年 10 月 20 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit 1ae0949,2020 年 11 月 2 日)

diff:添加忽略匹配更改的-I&lt;regex&gt;

签字人:Michał Kępień

添加一个新的差异选项,可以忽略所有行(更改、删除和添加)与给定正则表达式匹配的更改。
这类似于独立的diff 实用程序中的-I/--ignore-matching-lines 选项,可以用于例如忽略仅影响代码 cmets 的更改或在包含大量自动应用的修改的提交中查找不相关的更改(例如树范围的字符串替换)。

-G/-S 和新的-I 选项之间的区别在于后者根据每次更改过滤输出。

使用xdchange_t 的“忽略”字段将更改标记为是否忽略。
由于--ignore-blank-lines 使用相同的字段,因此--ignore-blank-lines-I 应用相同的大块发射规则。
这两个选项也可以在同一个 git 调用中一起使用(它们是互补的)。

xdl_mark_ignorable() 重命名为xdl_mark_ignorable_lines(),以表明它在逻辑上是xdl_mark_ignorable_regex() 的“兄弟”而不是其“父”。

diff-options 现在包含在其man page 中:

-I&lt;regex&gt;

--ignore-matching-lines=&lt;regex&gt;

忽略所有行匹配&lt;regex&gt;的更改。
可以多次指定此选项。

Examples:

git diff --ignore-blank-lines -I"ten.*e" -I"^[124-9]"

diff -I&lt;regexp&gt;”中的一个小内存泄漏已在 Git 2.31(2021 年第一季度)中得到纠正。

参见commit c45dc9ccommit e900d49(2021 年 2 月 11 日)Ævar Arnfjörð Bjarmason (avar)
(由 Junio C Hamano -- gitster -- 合并到 commit 45df6c4,2021 年 2 月 22 日)

diff:从{log,diff} -I 上的 regcomp() 插入内存​​泄漏

签字人:Ævar Arnfjörð Bjarmason

修复296d4a9 中的内存泄漏(“diff:添加忽略匹配更改的-I”,2020-10-20,Git v2.30.0-rc0 -- merge 列在batch #3)中释放它在新引入的diff_free() 中分配的内存。

296d4a9 中故意引入了此内存泄漏,请参阅discussion on a previous iteration of it

当时释放内存有点繁琐,但由于新引入的diff_free()不再是它,让我们使用它。

让我们保留diff_free_file() 的模式并添加diff_free_ignore_regex(),尽管(与"diff_free_file") 不同,我们不需要在其他地方调用它。
我认为这将比逐渐积累一个巨大的diff_free() 函数、在不相关的代码之间共享“int i”等更易读。

【讨论】:

  • 所有行匹配”要求使这有点繁琐。您可以通过调整上下文行的数量(例如,by Beni 提到的--unified=1最小化“所有行”遇到其他更改的机会,但如果出现以下情况,您不能丢弃无意义的更改它们与有趣的相邻。
  • @Michael 好点。我仍然认为这是对 git diff 的一个有趣的补充,尽管它很繁琐。
【解决方案3】:

使用git difftool 运行真正的diff

示例:https://github.com/cben/kubernetes-discovery-samples/commit/b1e946434e73d8d1650c887f7d49b46dcbd835a6
我创建了一个以我想要的方式运行diff 的脚本(这里我将curl --verbose 输出保存在repo 中,每次重新运行curl 时都会产生无聊的变化):

#!/bin/bash
diff --recursive --unified=1 --color \
     --ignore-matching-lines=serverAddress \
     --ignore-matching-lines='^\*  subject:' \
     --ignore-matching-lines='^\*  start date:' \
     --ignore-matching-lines='^\*  expire date:' \
     --ignore-matching-lines='^\*  issuer:' \
     --ignore-matching-lines='^< Date:' \
     --ignore-matching-lines='^< Content-Length:' \
     --ignore-matching-lines='--:--:--' \
     --ignore-matching-lines='{ \[[0-9]* bytes data\]' \
     "$@"

现在我可以运行 git difftool --dir-diff --extcmd=path/to/above/script.sh 并只看到有趣的变化。

关于 GNU diff -I aka --ignore-matching-lines 的一个重要警告:这只是防止这些行使块“有趣”,但是当这些更改与其他未忽略的更改出现在同一块中时,它仍然会显示它们。我在上面使用了--unified=1,通过使块更小(每次更改上下只有 1 个上下文行)来减少这种影响。

【讨论】:

    【解决方案4】:

    我认为我有一个使用管道和grep 的不同解决方案。我有两个文件需要检查不包括@@g:的差异,所以我这样做了(借用hereherehere

    $ git diff -U0 --color-words --no-index file1.tex file2.tex | grep -v -e "@@" -e "g:"
    

    这似乎起到了作用。颜色仍然存在。

    所以我假设您可以采用更简单的git diff 命令/输出并执行相同的操作。我喜欢这个的是它不需要创建新文件或重定向(管道除外)。

    【讨论】:

      猜你喜欢
      • 2010-12-25
      • 2018-08-14
      • 2014-04-18
      • 1970-01-01
      • 2014-05-18
      • 2013-11-19
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      相关资源
      最近更新 更多