如何在Git历史记录中grep(搜索)提交的代码
在过去的某个时候,我删除了一个文件或文件中的一些代码。我可以在内容(而不是提交消息)中grep吗 一个非常糟糕的解决方案是grep日志:如何在Git历史记录中grep(搜索)提交的代码,git,grep,diff,Git,Grep,Diff,在过去的某个时候,我删除了一个文件或文件中的一些代码。我可以在内容(而不是提交消息)中grep吗 一个非常糟糕的解决方案是grep日志: git log -p | grep <pattern> git日志-p | grep 但是,这不会立即返回提交散列。我使用了git 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”的行的修订”
选项允许您使用扩展POSIX regex,而不是搜索字符串。 示例(来源):--pickaxe 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