在Git代码存储库中,我想列出所有包含某个单词的提交。我尝试了这个
git log -p | grep --context=4 "word"
但它并不一定会返回文件名(除非它与我搜索的单词相差不到五行)。我也试过了
git grep "word"
但它只给我现在的文件,而不是历史。
如何搜索整个历史记录,以便跟踪特定单词的更改?我打算在代码库中搜索单词的出现情况以跟踪更改(在文件历史记录中搜索)。
git log的耙将找到带有更改的提交,包括git log -Sword的“word”
git log
git log -Sword
如果要查找提交消息包含给定单词的所有提交,请使用
$ git log --grep=word
如果你想找到文件内容中“word”被添加或删除的所有提交(更准确地说:“word”的出现次数发生变化的地方),即搜索提交内容,使用所谓的“耙”搜索
$ git log -Sword
在现代Git中,还有
$ git log -Gword
查找差异,其添加或删除的行匹配“word”(也是提交内容)。
有几件事要注意:
-G
-S
--pickaxe-regex
-S<regex> --pickaxe-regex
-G<regex>
#0留档有一个很好的解释的区别:
为了说明-S<regex> --pickaxe-regex和-G<regex>之间的区别,请考虑在同一文件中使用以下diff的提交:+ return frotz(nitfol, two->ptr, 1, 0);...- hit = frotz(nitfol, mf2.ptr, 1, 0);虽然git log -G"frotz\(nitfol"将显示此提交,但git log -S"frotz\(nitfol" --pickaxe-regex不会(因为该字符串的出现次数没有改变)。
为了说明-S<regex> --pickaxe-regex和-G<regex>之间的区别,请考虑在同一文件中使用以下diff的提交:
+ return frotz(nitfol, two->ptr, 1, 0);...- hit = frotz(nitfol, mf2.ptr, 1, 0);
虽然git log -G"frotz\(nitfol"将显示此提交,但git log -S"frotz\(nitfol" --pickaxe-regex不会(因为该字符串的出现次数没有改变)。
git log -G"frotz\(nitfol"
git log -S"frotz\(nitfol" --pickaxe-regex
要在正则表达式上使用布尔连接器:
git log --grep '[0-9]*\|[a-z]*'
此正则表达式在提交消息中搜索正则表达式[0-9]*或[a-z]*。
维姆逃犯对于Vim中的这种检查是通用的。
使用:Ggrep来做到这一点。有关更多信息,您可以安装vim-fugitive并通过:help Grep查找教程。这一集:探索a g it存储库的历史将指导您完成所有这些。
:Ggrep
:help Grep
另一种方法/语法是:git log -S "word"像这样你可以搜索例子git log -S "with whitespaces and stuff @/#ü !"
git log -S "word"
git log -S "with whitespaces and stuff @/#ü !"
经过大量的实验,我可以推荐以下内容,它显示了引入或删除包含给定正则表达式的行的提交,并显示每个行中的文本更改,颜色显示添加和删除的单词。
git log --pickaxe-regex -p --color-words -S "<regexp to search for>"
虽然需要一段时间才能运行…;-)
您可以尝试以下命令:
git log --patch --color=always | less +/searching_string
或者以以下方式使用grep:
grep
git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'
在要搜索的父目录中运行此命令。
如果您想搜索敏感数据以将其从Git历史记录中删除(这就是我在这里登陆的原因),有一些工具可以做到这一点。GitHub作为针对该问题的专用帮助页面。
以下是文章的要点:
BFG回收清洁剂是git filter-分支的更快、更简单的替代方案,用于删除不需要的数据。例如,要删除包含敏感数据的文件并保持最新提交不变),请运行:
bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA
要替换passwords.txt中列出的所有文本,无论它可以在存储库的历史记录中找到,请运行:
bfg --replace-text passwords.txt
有关完整使用和下载说明,请参阅BFG回收清洁剂留档。
这与BFG(Git过滤器分支-不要与git-filter目录混淆)和git-filter-repo开发完成结合使用很有用。它只是获取文件路径,以便您可以将它们提供给我刚才提到的两个工具之一。
# Get all unique filepaths of files matching 'password'# Source: https://stackoverflow.com/a/69714869/10830091git rev-list --all | (while read revision; dogit grep -F --files-with-matches 'password' $revision | cat | sed "s/[^:]*://"done) | sort | uniq
# Get all unique filenames matching 'password'# Source: https://stackoverflow.com/a/69714869/10830091git rev-list --all | (while read revision; dogit grep -F --files-with-matches 'password' $revision | cat | sed "s/[^:]*://"done) | xargs basename | sort | uniq
第二个命令对BFG很有用,因为它只接受文件名而不接受repo相对/系统绝对路径。
就这样。享受使用这些Bash片段给我带来的痛苦。我讨厌Bash,那我为什么还要继续使用它呢?
以下任一选项的含义相同(git-rep留档):
-l
--files-with-matches
--name-only
而不是显示每一个匹配的行,只显示包含的文件的名称区块链
至于-F,它只是意味着使用固定字符串而不是模式解释的正则表达式。一个来源。
-F
另一个有用的注意事项属于这里:你可以把-i或--ignore-case扔进不区分大小写。
-i
--ignore-case
sed "s/[^:]*://"
来源
| sort | uniq
谁想要重复的路径?不是你,不是我!哦,嘿,看,他们也是排序的!享受。
来源:我,我用了很久了,只要我能记得。(man sort和man uniq)
man sort
man uniq
xargs basename
你会认为| basename会起作用,但事实并非如此。它不接受输入标准输入,而是作为命令行参数。这是一个解释。去想象!basename基本上返回没有前导路径的茎文件名。man basename。
| basename
basename
man basename
当然,只要在最后打一个realpath。像这样:
realpath
) | sort | uniq | xargs realpath
当然,您必须使用xargs,因为realpath不使用标准输入进行输入。它使用命令行参数。就像dirname一样。
xargs
dirname