93

有没有办法显示按给定模式过滤的 git-diff。

就像是

git grepdiff pattern

changed file
+++ some sentence with pattern
changed file 2
--- some other pattern

不幸的是,最简单的解决方案还不够好

git diff | grep pattern 

+++ some sentence with pattern
--- some other pattern
# not an option as doesn't put the filename close to the match

我使用 awk 提供了一种解决方法

git diff | awk "/\+\+\+/{f = \$2}; /PATTERN/ {print f \$0} "

但很想知道有一个命令。

4

10 回答 10

113

不确定,但git diff -G <regex>标志不行吗?

-G <正则表达式>

Look for differences whose added or removed line matches the given <regex>.
于 2012-09-17T15:41:57.387 回答
13

你试过了吗git diff -S<string>git diff -G".*string.*"请注意,它们不是等效的,请参阅有关镐的文档以了解 -S 的作用。

于 2012-09-17T15:49:05.467 回答
12

另一种可能性是查看整个差异并使用普通less命令(类型/然后是模式)搜索输出。

当您使用less配置为在匹配之前显示一些行时--jump-target=N,这非常有用。试试这样:

PAGER="/usr/bin/less --jump-target=10" git diff

这意味着匹配应该显示在第 10 行(上面显示 9 行上下文),这可能足以同时看到文件名。

您还可以使用 eg--jump-target=.5将匹配项放置在屏幕中间。

于 2012-09-17T15:56:59.567 回答
5

我使用git log -p,它打开较少(但可配置),而它又可以用/. 还有git log -S <searchword>

于 2012-09-17T15:42:43.193 回答
3

我认为您对“grep”diff输出的方法是最好的解决方法。

您可以使用 sed 改进您的 awk 脚本:

colored="(^[\[[0-9;]*[a-zA-Z])"
marker="^$colored+diff"
pattern="^$colored+.*(\+|\-).*PATTERN"
git diff --color | sed -rn -e "/$marker/! H; /$marker/ ba; $ ba; b; :a; x; /$pattern/ p"
  • colored: 正则表达式匹配终端彩色线
  • marker:标记以匹配来自不同diff大块的划分,以彩色“diff”开头的行
  • pattern:要搜索的模式,以彩色“+”或“-”开头并包含“PATTERN”的行

这将打印完整的差异大块,添加或删除 PATTERN,同时保持有用的彩色输出。

请注意,^[incolored应该是实际的字面量^[。您可以通过按Ctrl+ VCtrl+在 bash 中键入它们[

于 2018-05-28T15:55:34.850 回答
2

这是一个自定义 diff 工具,它允许 grepping 内部更改(但不是上下文):

用法

GIT_EXTERNAL_DIFF="mydiff --grep foo" git diff

这将输出您的更改中包含的那些行foo(包括foo由于您的更改而消失的行)。可以使用任何 grep 模式来代替foo.

每个输出行都以以下前缀开头:

filename: oldlinenum: newlinenum|

该脚本也可以在没有--grep选项的情况下使用,在这种情况下,它只是如上所述格式化完整差异(即提供完整上下文)。

我的差异

#!/bin/bash

my_diff()
{
    diff --old-line-format="$1"':%6dn:      |-%L'     \
         --new-line-format="$1"':      :%6dn|+%L'     \
         --unchanged-line-format="$1"':%6dn:%6dn| %L' \
         $2 $3
}

if [[ $1 == '--grep' ]]
then
    pattern="$2"
    shift 2
    my_diff "$1" "$2" "$5"|grep --color=never '^[^|]\+|[-+].\+'"$pattern"'.*'
else
    my_diff "$1" "$2" "$5"
fi

exit 0
于 2016-09-02T17:17:50.103 回答
2

我一直非常满意地使用它:)

grep -ri <MY_PATTERN> $(git diff 790e26393d --name-only) 
于 2020-09-16T19:09:15.073 回答
1

在 Windows 上,一个简单的解决方案是:

git diff -U0 | findstr string

如果要按文件名分组,请使用此

FOR /F "usebackq delims==" %i IN (`git diff --name-only`) do git diff -U0 %~fi | findstr string
于 2018-02-01T11:22:07.217 回答
1

这为我完成了工作,我希望它可以帮助某人:

git diff | grep  -P '^\+|^\-'
于 2018-03-07T16:52:33.060 回答
0

提供的解决方案并不完全符合我的需求,这解决了我的问题。

(
    START_DIFF=abc123
    END_DIFF=123dcf 

    # loop over all the files that have changed inside the diff
    # you can add a `| grep '<ext>$'` to the end of `--name-only`
    # if you need to be more aggresive with the filtering / or 
    # make it go faster...
    for file in $(git diff $START_DIFF $END_DIFF --name-only); do
        # loop over every line of the diff FOR that file.
        while IFS= read -r line; do
            # prepend the file name to every line
            echo "$file:$line"
        done < <(git diff $START_DIFF $END_DIFF $file)
    done
) | grep what-youre-looking-for

我无法让行号工作,但我真的不需要它们来让它们工作。附加的文件名对我来说已经足够了。


我的确切问题:

在 70 多个文件中查找添加了 afrom __future__ import ..或 a的所有文件。-*- coding: utf-8 -*-

(
    START_DIFF=branch-a
    END_DIFF=HEAD
    for file in $(git diff $START_DIFF $END_DIFF --name-only); do
        while IFS= read -r line; do
            echo "$file:$line"
        done < <(git diff $START_DIFF $END_DIFF $file)
    done
) | grep ':+' | awk '(/import/ && /__future/) || (/coding/)'

输出如下所示:

....
app/tests/test_views.py:+# -*- coding: utf-8 -*-
app/tests/test_views.py:+from __future__ import absolute_import
app/tests/test_views.py:+from __future__ import division
app2/tests/test_views.py:+from __future__ import division
...
于 2021-10-20T22:50:20.473 回答