仅显示基于正则表达式的差异/补丁的相关块


20

git log -G<regex> -p是一个很棒的工具,可以在代码库的历史记录中搜索与指定模式匹配的更改。但是,将相关的块放置在差异较大/不相关的块的海洋中的diff / patch输出中可能会让人不知所措。

当然可以在的输出中搜索git log原始的字符串/正则表达式,但这并不能减少视觉噪音和许多无关更改的干扰。

继续阅读git log,我看到有--pickaxe-all,它与我想要的完全相反:它扩大了输出(扩展到整个变更集),而我想将其限制(到特定的块)。

本质上,我正在寻找一种“智能”地将差异/补丁解析为单个块的方法,然后针对每个块执行搜索(仅针对更改的行),丢弃不匹配的块,然后将其输出那做。

我所描述的工具是否存在?有没有更好的方法来获得匹配的/受影响的大块头?

我已经完成了一些初步的研究...

  • 如果可以grep比较/修补程序输出并使上下文选项值动态(例如,通过正则表达式而不是行数),则可能就足够了。但是grep并不是完全按照这种方式构建的(我也不一定要求该功能)。

  • 我找到了patchutils套件,最初听起来好像它可以满足我的需求。但是在阅读其man页面之后,这些工具似乎无法处理基于正则表达式的匹配块。(不过,他们可以接受帅哥列表...)

  • 我终于遇到了splitpatch.rb,它似乎可以很好地处理补丁的解析,但是需要对其进行显着扩展,以通过stdin,匹配所需的块,然后输出块来处理读取补丁。


1
不完全是您的要求,但是尝试git log -Gfoo | 少+ / foo
James Youngman'3

Answers:


7

此处描述了/programming//a/35434714/5305907一种执行所需内容的方法。有效:

git diff -U1 | grepdiff 'console' --output-matching=hunk

它仅显示与给定字符串“ console”匹配的块。


谢谢。grepdiff基本上就是我想要的;我一定错过了大块头匹配选项!但是 ... ... git commit信息被剥夺了grepdiff,因此,一旦找到相关的块,就必须从diff头中的object / blob sha区分commit sha-相当昂贵的操作。(请参阅stackoverflow.com/a/223890/2284440)类似git find-object SHA --reverse | head -1 | cut -c 1-7 | { read sha ; git log -1 $sha; }
wrksprfct

还请注意,有一个golang版本,grepdiff在接受的参数方面更加准系统。请注意,当匹配的块是diff中的最后一个块时,它不正确地包含了以下提交的git commit标头-这使我完全感到困惑,直到我意识到发生了什么!
wrksprfct

0

并非完全符合您的要求,但通过添加块进行grep的一种方法是交互式添加模式。这要求您在感兴趣的补丁之后签出提交

git checkout COMMIT_ID

然后在VCS中再返回一步,但不在工作目录中

git reset --soft HEAD^

(此时,索引和工作目录之间的差异将与您感兴趣的补丁相对应。)

您现在可以执行git add -p。这将启动一个交互式会话,该会话具有一个/选项,可让您找到与某些正则表达式匹配的行。如果您实际上想进一步处理这些补丁(例如,准备部分的樱桃拣选),则特别有用。

不幸的是,至少现在该/命令add -p仅在单个文件中起作用,因此您可能需要跳过几个不相关的文件。


0

在上面@nagu的答案以及其他链接的答案的基础上,我git log -G仅能显示相关的帅哥。

  1. 首先在$ PATH中的某个位置创建一个包含以下内容的脚本:

    #!/bin/bash
    
    # pickaxe-diff : external diff driver for Git.
    #                To be used with the pickaxe options (git [log|show|diff[.*] [-S|-G])
    #                to only show hunks containing the searched string/regex.
    
    path=$1
    old_file=$2
    old_hex=$3
    old_mode=$4
    new_file=$5
    new_hex=$6
    new_mode=$7
    
    filtered_diff=$(diff -u -p $old_file $new_file | \
                    grepdiff "$GREPDIFF_REGEX" --output-matching=hunk | \
                    grep -v -e '+++ ' -e '--- ')
    
    a_path="a/$path"
    b_path="b/$path"
    
    echo "diff --git $a_path $b_path"
    echo "index $old_hex..$new_hex $old_mode"
    echo "--- $a_path"
    echo "+++ $b_path"
    echo "$filtered_diff"
  2. 调用git log -G并告诉Git将pickaxe-diff脚本用作外部差异驱动程序:

    export GREPDIFF_REGEX=<string>; 
    GIT_EXTERNAL_DIFF=pickaxe-diff git log -p --ext-diff -G $GREPDIFF_REGEX

    这将仅使用pickaxe-diff脚本来生成差异,因此其余git log输出(提交哈希,消息等)将保持不变。

需要注意
的方式,Git的鹤嘴锄的工作是,它限制了输出到文件,其帅哥改变给定的字符串/正则表达式。这意味着,如果这些文件中的另一个大块也包含搜索字符串/正则表达式,但没有更改,则仍将与上面的脚本一起显示。这是grepdiff的局限性。patchutils项目中有一个开放的拉取请求,用于--only-matching向grepdiff 添加一个标志,这将提供所需的功能以正确过滤出这些杂物。


我在这个要点上写下了自己的解决方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.