简体   繁体   English

grep 与 git 差异如何?

[英]How to grep the git diff?

Is there a way to show the git-diff filtered by a given pattern.有没有办法显示按给定模式过滤的 git-diff。

Something like就像是

git grepdiff pattern

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

Unfortunately the simplest solution is not good enough不幸的是,最简单的解决方案还不够好

git diff | grep pattern 

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

I came with a workaround using awk我使用 awk 提供了一种解决方法

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

But would love to find out that there is a command for this.但很想知道有一个命令。

Not sure but isn't git diff -G <regex> flag OK?不确定但不是git diff -G <regex>标志好吗?

-G < regex> -G <正则表达式>

 Look for differences whose added or removed line matches the given <regex>.

Have you tried git diff -S<string> or git diff -G".*string.*" ?您是否尝试过git diff -S<string>git diff -G".*string.*" Note that they are not equivalent, see the documentation about pickaxe for what -S does.请注意,它们不是等价的, 有关-S 的作用,请参阅有关镐的文档

Another possibility would be to view the whole diff and search the output using the normal less commands (type / and then the pattern).另一种可能性是查看整个差异并使用普通的less命令(输入/然后输入模式)搜索输出。

When you have less configured to show some lines before the match using --jump-target=N , this is pretty useful.当您使用--jump-target=N less配置以在匹配之前显示一些--jump-target=N ,这非常有用。 Try it like this:像这样尝试:

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

This means that the match should be shown on line 10 (shows 9 lines of context above), which may be enough to also see the file name.这意味着匹配应该显示在第 10 行(上面显示了 9 行上下文),这可能足以看到文件名。

You can also use eg --jump-target=.5 to make it position the match in the middle of the screen.您还可以使用例如--jump-target=.5将匹配项定位在屏幕中间。

I use git log -p , which opens less (configurable, though), which in turn can be searched for with / .我使用git log -p ,它打开较少(但可配置),而后者又可以使用/进行搜索。 There's also git log -S <searchword> .还有git log -S <searchword>

I think your approach to "grep" diff output is the best workaround.我认为您对“grep” diff输出的方法是最好的解决方法。

You may improve your awk script by using sed:您可以使用 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 : regex to match terminal colored lines colored :正则表达式匹配终端彩色线条
  • marker : marker to match division from differents diff hunks, lines starting with colored "diff" marker :标记以匹配不同diff大块的划分,以彩色“差异”开头的行
  • pattern : pattern to search for, lines starting with colored "+" or "-" and containing "PATTERN" pattern :要搜索的模式,以彩色“+”或“-”开头并包含“PATTERN”的行

This will print full diff hunks, with added or removed PATTERN, also maintaining useful colored output.这将打印完整的差异块,添加或删除 PATTERN,同时保持有用的彩色输出。

Note that ^[ in colored should be actual, literal ^[ .请注意, ^[ colored应该是实际的文字^[ You can type them in bash by pressing Ctrl + V , Ctrl + [您可以通过按Ctrl + VCtrl + [在 bash 中键入它们

Here is a custom diff tool that allows grepping inside changes (but not the context):这是一个自定义差异工具,允许在内部更改(但不是上下文):

Usage用法

GIT_EXTERNAL_DIFF="mydiff --grep foo" git diff

This will output those lines in your changes that contain foo (including lines where foo disappeared because of your changes).这将输出更改中包含foo那些行(包括foo由于您的更改而消失的行)。 Any grep pattern can be used instead of foo .可以使用任何 grep 模式代替foo

Each output line starts with the following prefix:每个输出行都以以下前缀开头:

filename: oldlinenum: newlinenum|

The script can also be used without the --grep option, in which case it simply formats the full diff (ie providing full context) as described above.该脚本也可以在没有--grep选项的情况下使用,在这种情况下,它只是按照上述方式格式化完整的差异(即提供完整的上下文)。

mydiff我的差异

#!/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

这对我有用,我希望它会帮助某人:

git diff | grep  -P '^\+|^\-'

我一直很满意地使用它:)

grep -ri <MY_PATTERN> $(git diff 790e26393d --name-only) 

On Windows, a simple solution is:在 Windows 上,一个简单的解决方案是:

git diff -U0 | findstr string

If you want grouping by filename, use this如果要按文件名分组,请使用此

FOR /F "usebackq delims==" %i IN (`git diff --name-only`) do git diff -U0 %~fi | findstr string

The solutions offered didn't exactly fit my needs, this solved my issue.提供的解决方案并不完全符合我的需求,这解决了我的问题。

(
    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 xyz

I could not get the line numbers working, but I didn't really need them to get them to work.我无法让行号工作,但我真的不需要它们来让它们工作。 The prepended filename was enough for me.前置文件名对我来说已经足够了。


My exact issue:我的确切问题:

Find all the files that added either a from __future__ import .. or a -*- coding: utf-8 -*- out of 70+ files. from __future__ import ..文件中找出所有添加了from __future__ import ..-*- 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/)'

The output looks like this:输出如下所示:

....
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
...

Ugly, potentially inaccurate, but might be enough to get by if you're just eyeballing it:丑陋,可能不准确,但如果你只是盯着它可能就足够了:

git diff origin/master | grep -Eo "(^diff.*|some-keyword)"

Where file1.txt contains some-keyword once, and file3.txt contains some-keyword 3 times:其中file1.txt包含some-keyword一次, file3.txt包含some-keyword 3 次:

Outputs:输出:

diff --git a/path/to/file1.txt b/path/to/file1.txt
some-keyword
diff --git a/path/to/file2.txt b/path/to/file2.txt
diff --git a/path/to/file3.txt b/path/to/file3.txt
some-keyword
some-keyword
some-keyword
diff --git a/path/to/file4.txt b/path/to/file4.txt

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM