如何在Git历史记录中grep(搜索)提交的代码

如何在Git历史记录中grep(搜索)提交的代码,git,grep,diff,Git,Grep,Diff,在过去的某个时候,我删除了一个文件或文件中的一些代码。我可以在内容(而不是提交消息)中grep吗 一个非常糟糕的解决方案是grep日志: git log -p | grep <pattern> git日志-p | grep 但是,这不会立即返回提交散列。我使用了git grep,但没有任何效果。那么,您是否正在尝试grep浏览旧版本的代码,以查看最后存在的内容 如果我这样做,我可能会使用。使用二分法,您可以指定一个已知的好版本、一个已知的坏版本,以及一个简单的脚本,该脚本执行检查

在过去的某个时候,我删除了一个文件或文件中的一些代码。我可以在内容(而不是提交消息)中grep吗

一个非常糟糕的解决方案是grep日志:

git log -p | grep <pattern>
git日志-p | grep

但是,这不会立即返回提交散列。我使用了
git grep
,但没有任何效果。

那么,您是否正在尝试grep浏览旧版本的代码,以查看最后存在的内容

如果我这样做,我可能会使用。使用二分法,您可以指定一个已知的好版本、一个已知的坏版本,以及一个简单的脚本,该脚本执行检查以查看版本是好是坏(在本例中,使用grep查看您要查找的代码是否存在)。运行此命令将在删除代码时找到。

您应该使用的选项

要搜索
Foo

git log -SFoo -- path_containing_change
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change
更多信息,请参阅


如评论所述:

  • 查找引入或删除
    实例的差异。 它通常意味着“添加或删除带有“Foo”的行的修订”

  • --pickaxe regex
    选项允许您使用扩展POSIX regex,而不是搜索字符串。 示例(来源):
    git日志-S“frotz\(nitfol”--pickaxe regex


如前所述,此搜索区分大小写-他打开了一个关于如何搜索不区分大小写的页面。

要搜索提交内容(即源代码的实际行,而不是提交消息等),您需要执行以下操作:

git grep <regexp> $(git rev-list --all)
这将grep通过
regexp
的所有提交文本

在这两个命令中传递路径的原因是,
rev list
将返回修订列表,其中发生了对
lib/util
的所有更改,但您还需要传递到
grep
,以便它只在
lib/util
中搜索

想象一下下面的场景:
grep
可能会在其他文件上找到相同的
,这些文件包含在
rev list
返回的同一版本中(即使该版本上的文件没有更改)

以下是搜索源代码的其他一些有用方法:

在工作树中搜索与正则表达式regexp匹配的文本:

git grep <regexp>
git grep <regexp> $(git rev-list --all)
git grep <regexp> $(git rev-list <rev1>..<rev2>)
git grep
在工作树中搜索与正则表达式regexp1或regexp2匹配的文本行:

git grep -e <regexp1> [--or] -e <regexp2>
git grep-e[--or]-e
在工作树中搜索与正则表达式regexp1和regexp2匹配的文本行,仅报告文件路径:

git grep -l -e <regexp1> --and -e <regexp2>
git grep-l-e--and-e
在工作树中搜索具有与正则表达式regexp1匹配的文本行和与正则表达式regexp2匹配的文本行的文件:

git grep -l --all-match -e <regexp1> -e <regexp2>
git grep-l——所有匹配-e-e
在工作树中搜索文本匹配模式的更改行:

git diff --unified=0 | grep <pattern>
git diff--unified=0 | grep
搜索与正则表达式regexp匹配的文本的所有修订:

git grep <regexp>
git grep <regexp> $(git rev-list --all)
git grep <regexp> $(git rev-list <rev1>..<rev2>)
git grep$(git rev list--all)
搜索rev1和rev2之间的所有修订,以查找与正则表达式regexp匹配的文本:

git grep <regexp>
git grep <regexp> $(git rev-list --all)
git grep <regexp> $(git rev-list <rev1>..<rev2>)
git grep$(git版本列表..)
我将其应用于Windows(多亏了):

FOR/F%x IN(“'git rev list--all”')DO@git grep%x>out.txt

请注意,对于我来说,由于某种原因,删除此正则表达式的实际提交没有出现在命令的输出中,而是在它之前出现一次提交。

我最喜欢的方法是使用
git log
-G
选项(在版本1.7.4中添加)


由于“hello”在文件中出现的次数在此提交前后相同,因此使用
-Shello
时它将不匹配。但是,由于与
hello
匹配的行发生了更改,如果要浏览代码更改,则将使用
-Ghello

显示提交(查看整个历史中给定单词的实际变化)选择
patch
模式-我发现了一个非常有用的组合:

git log -p
# Hit '/' for search mode.
# Type in the word you are searching.
# If the first search is not relevant, hit 'n' for next (like in Vim ;) )
在PowerShell中工作

git grep -n <regex> $(git rev-list --all)

任何版本、任何文件中搜索(unix/linux):


对于试图在Sourcetree中执行此操作的任何其他人,UI中没有直接的命令(从1.6.21.0版开始)。但是,您可以通过打开Terminal窗口(主工具栏中提供的按钮)并在其中复制/粘贴,来使用接受答案中指定的命令

注意:Sourcetree的“搜索”视图可以部分为您执行文本搜索。按Ctrl+3转到“搜索”视图(或单击底部可用的搜索选项卡)。从最右侧,将“搜索类型”设置为“文件更改”,然后键入要搜索的字符串。与上述命令相比,此方法具有以下限制:

  • Sourcetree仅显示其中一个已更改文件中包含搜索词的提交。查找包含搜索文本的确切文件也是一项手动任务
  • 不支持正则表达式

  • git log
    是一种更有效的跨所有分支搜索文本的方法,尤其是当存在许多匹配项,并且您希望首先看到更近期(相关)的更改时

    git log -p --all -S 'search string'
    git log -p --all -G 'match regular expression'
    
    这些日志命令列出了添加或删除给定搜索字符串/regex(通常是最新的)的提交。
    -p
    选项会在添加或删除模式的位置显示相关的差异,以便您可以在上下文中看到它

    找到添加要查找的文本的相关提交(例如8beeff00d)后,查找包含提交的分支:

    git branch -a --contains 8beeff00d
    

    是对的一个调整,因此它在搜索时显示结果,而不仅仅是在最后(在大型存储库中可能需要很长时间)。

    为简单起见,我建议使用GUI:。它非常灵活

  • 要搜索代码:

  • 要搜索文件:

  • 当然,它也支持re
    git log -p --all -S 'search string'
    git log -p --all -G 'match regular expression'
    
    git branch -a --contains 8beeff00d
    
    git rev-list --all | xargs -n 5 git grep EXPRESSION
    
    git grep --cached "text_to_find"
    
    git log -S "<words/phrases i am trying to find>" --all --oneline  --graph
    
    git log --follow -p -S 'search-string' <file-path>
    
    git log --pretty=%h -pS pattern | diffmarkup | grep pattern
    
    %option main 8bit nodefault
            // vim: tw=0
    %top{
            #define _GNU_SOURCE 1
    }
    %x commitheader
    %x diffheader
    %x hunk
    %%
            char *afile=0, *bfile=0, *commit=0;
            int aline,aremain,bline,bremain;
            int iline=1;
    
    <hunk>\n        ++iline; if ((aremain+bremain)==0) BEGIN diffheader;
    <*>\n   ++iline;
    
    <INITIAL,commitheader,diffheader>^diff.*        BEGIN diffheader;
    <INITIAL>.*     BEGIN commitheader; if(commit)free(commit); commit=strdup(yytext);
    <commitheader>.*
    
    <diffheader>^(deleted|new|index)" ".*   {}
    <diffheader>^"---".*            if (afile)free(afile); afile=strdup(strchrnul(yytext,'/'));
    <diffheader>^"+++".*            if (bfile)free(bfile); bfile=strdup(strchrnul(yytext,'/'));
    <diffheader,hunk>^"@@ ".*       {
            BEGIN hunk; char *next=yytext+3;
            #define checkread(format,number) { int span; if ( !sscanf(next,format"%n",&number,&span) ) goto lostinhunkheader; next+=span; }
            checkread(" -%d",aline); if ( *next == ',' ) checkread(",%d",aremain) else aremain=1;
            checkread(" +%d",bline); if ( *next == ',' ) checkread(",%d",bremain) else bremain=1;
            break;
            lostinhunkheader: fprintf(stderr,"Lost at line %d, can't parse hunk header '%s'.\n",iline,yytext), exit(1);
            }
    <diffheader>. yyless(0); BEGIN INITIAL;
    
    <hunk>^"+".*    printf("%s:%s:%d:%c:%s\n",commit,bfile+1,bline++,*yytext,yytext+1); --bremain;
    <hunk>^"-".*    printf("%s:%s:%d:%c:%s\n",commit,afile+1,aline++,*yytext,yytext+1); --aremain;
    <hunk>^" ".*    ++aline, ++bline; --aremain; --bremain;
    <hunk>. fprintf(stderr,"Lost at line %d, Can't parse hunk.\n",iline), exit(1);
    
    for commit in $(git rev-list --all); do 
        # search only lines starting with + or -
        if  git show "$commit" | grep "^[+|-].*search-string"; then 
            git show --no-patch --pretty=format:'%C(yellow)%h %Cred%ad %Cblue%an%Cgreen%d %Creset%s' --date=short $commit
        fi  
    done
    
    csshx$ for commit in $(git rev-list --all); do 
    >     if  git show "$commit" | grep "^[+|-].*As csshX is a command line tool"; then 
    >         git show --no-patch --pretty=format:'%C(yellow)%h %Cred%ad %Cblue%an%Cgreen%d %Creset%s' --date=short $commit
    >     fi  
    > done
    
    +As csshX is a command line tool, no special installation is needed. It may
    987eb89 2009-03-04 Gavin Brock Added code from initial release