如何找到在任何分支中引入了字符串的Git提交?


396

我希望能够找到在任何分支的任何提交中引入的某个字符串,我该怎么做?我找到了一些东西(我为Win32修改了),但git whatchanged似乎并没有考虑其他分支(忽略py3k块,这只是一个msys / win换行修复)

git whatchanged -- <file> | \
grep "^commit " | \
python -c "exec(\"import sys,msvcrt,os\nmsvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)\nfor l in sys.stdin: print(l.split()[1])\")" | \
xargs -i% git show origin % -- <file>

解决方案是否缓慢并不重要。


Answers:


685

你可以做:

git log -S <whatever> --source --all

查找所有添加或删除了固定字符串的 提交whatever。该--all参数表示从每个分支开始,并且--source表示显示哪个分支导致找到该提交。添加-p以显示每个提交也会引入的补丁通常很有用。

从1.7.4开始的git版本也具有类似的-G选项,该选项采用正则表达式。实际上,这具有不同的(并且更明显的)语义,这在Junio Hamano的博客文章中得到了解释。

正如thameera在评论中指出的那样,如果搜索词包含空格或其他特殊字符,则需要在其周围加上引号,例如:

git log -S 'hello world' --source --all
git log -S "dude, where's my car?" --source --all

这是-G用于查找出现的示例function foo() {

git log -G "^(\s)*function foo[(][)](\s)*{$" --source --all

19
+1追求卓越。指向-S是一回事,可以更好地进行解释。另外,我喜欢使用--decorate来查看事物的分支内容
sehe 2011年

7
@sehe:感谢您的好评。我想值得注意的是,--decorate仅将分支名称添加到每个分支末端的提交中。在实践中我真的不使用--source--decorate,而是使用git branch -a --contains <commit-hash>以找到分支包含的承诺,我感兴趣的
马克Longair

3
添加-p也可以查看内联差异,FWIW
rogerdpack 2014年

1
@MarkLongair它不显示合并中所做的更改。还有建议显示这些吗?
Pahlevi Fikri Auliya 2015年

2
对我而言,这仅在删除 -S和搜索词(即)之间的空格时有效git log -S"dude, where's my car?" --source --all。@ribamar还在下面的答案中写道,但是在该最高答案旁边可能会轻易被忽略。
bug313


20

Mark Longair的回答很好,但是我发现这个更简单的版本对我有用

git log -S whatever

24
为了澄清起见,如果您要查找的提交位于中HEAD,则可以很好地工作,但是此特定问题专门询问了有关在存储库中所有分支中进行查找的问题。
Mark Longair

18

困惑与相同的答案:

$ git config --global alias.find '!git log --color -p -S '
  • 因为其他方式,所以git不能将参数正确传递给-S。看到这个回应
  • --color-p有助于准确显示“已更改”

现在你可以做

$ git find <whatever>

要么

$ git find <whatever> --all
$ git find <whatever> master develop

6
git log -S"string_to_search" # options like --source --reverse --all etc

注意不要在S和“ string_to_search”之间使用空格。在某些设置(git 1.7.1)中,您将收到以下错误:

fatal: ambiguous argument 'string_to_search': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

2

尽管这并不能直接回答您的问题,但我认为将来可能对您来说是一个很好的解决方案。我看到了代码的一部分,这很糟糕。不知道是谁写的,什么时候写的。我可以看到文件中的所有更改,但是很明显,代码已从其他文件移到了这个文件中。我想找到真正添加它的人。

为此,我使用了Git bisect,它很快就让我找到了罪人。

我跑了git bisect start,然后git bisect bad,因为签出的修订版出现了问题。由于我不知道问题何时发生,因此我将第一次提交的目标定为“好” git bisect good <initial sha>

然后,我一直在仓库中搜索错误的代码。当我找到它时,我就跑了git bisect bad,而当它不在时:git bisect good

在大约11个步骤中,我涵盖了大约1000个提交,并找到了确切的提交,并在其中引入了问题。太棒了


2

不确定为什么接受的答案在我的环境中不起作用,最后我在命令下运行以获取所需的内容

git log --pretty=format:"%h - %an, %ar : %s"|grep "STRING"
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.