在一个Git代码库中,我想列出所有包含某个单词的提交。
git log -p | grep --context=4 "word"
但它不一定给予文件名(除非它与我搜索的单词相距不到五行)。
git grep "word"
但它只给我现在的文件而不是历史。如何搜索整个历史记录以便跟踪特定单词的更改?我打算搜索代码库中出现的单词以跟踪更改(在文件历史记录中搜索)。
5ktev3wc1#
如果你想找到所有的提交,其中 commit message 包含一个给定的单词,使用
$ git log --grep=word
如果你想找到所有在 file contents 中添加或删除了“word”的提交(更确切地说:其中“word”的出现次数改变),即搜索 * 提交内容 *,使用所谓的“pickaxe”搜索
$ git log -Sword
在现代的Git中也有
$ git log -Gword
查找添加或删除的行与“word”匹配的 * 差异 *(也是 * 提交内容 *)。需要注意的几点:
-G
-S
--pickaxe-regex
-S<regex> --pickaxe-regex
-G<regex>
git diff documentation有一个很好的解释:为了说明-S<regex> --pickaxe-regex和-G<regex>之间的区别,考虑在同一个文件中具有以下差异的提交:
git 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不会(因为该字符串的出现次数没有改变)。这将显示包含搜索词的提交,但如果你想看到这些提交中的实际变化,你可以使用--patch:
git log -G"frotz\(nitfol"
git log -S"frotz\(nitfol" --pickaxe-regex
--patch
$ git log -G"searchTerm" --patch
然后可以将其通过管道传输到grep,以隔离输出,只显示带有该搜索词的提交差异行。一个常见的用例是显示自提交以来并包括给定提交(在本示例中为3b5ab0f2a1)的带有该搜索词的提交差异行,如下所示:
grep
3b5ab0f2a1
$ git log 3b5ab0f2a1^.. -G"searchTerm" --patch | grep searchTerm
nbysray52#
git log的pickaxe将找到包含“word”的修改的提交
git log
ymdaylpp3#
经过大量的实验,我可以推荐以下内容,它显示了引入或删除包含给定regexp的行的提交,并显示了每个提交中的文本更改,并用颜色显示了添加和删除的单词。
git log --pickaxe-regex -p --color-words -S "<regexp to search for>"
虽然需要一段时间才能运行…;- )
vxf3dgd44#
另一种方法/语法是:git log -S "word"这样你可以搜索例如git log -S "with whitespaces and stuff @/#ü !"
git log -S "word"
git log -S "with whitespaces and stuff @/#ü !"
mtb9vblg5#
您可以尝试以下命令:
git log --patch --color=always | less +/searching_string
或者按以下方式使用grep:
git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'
在要搜索的父目录中运行此命令。
iyfjxgzm6#
要在正则表达式上使用布尔连接符,请执行以下操作:
git log --grep '[0-9]*\|[a-z]*'
此正则表达式在提交消息中搜索正则表达式[0-9]* 或[a-z]*。
2ic8powd7#
这在与BFG(Git过滤器分支-不要与 * git-filter-branch * 混淆)和git-filter-repo结合使用时非常有用。它只是获取文件路径,以便您可以将它们提供给我刚才提到的两个工具之一。
# Get all unique filepaths of files matching 'password' # Source: https://stackoverflow.com/a/69714869/10830091 git rev-list --all | ( while read revision; do git 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/10830091 git rev-list --all | ( while read revision; do git grep -F --files-with-matches 'password' $revision | cat | sed "s/[^:]*://" done ) | xargs basename | sort | uniq
第二个命令对BFG很有用,因为它只接受文件名,而不接受repo-relative/system-absolute路径。好了。享受使用这些Bash片段给我带来的痛苦吧。我讨厌Bash,那我为什么还要继续使用它呢?
以下任何一个选项的含义都是相同的(git-rep文档):
-l
--files-with-matches
--name-only
只显示包含Blockquote的文件的名称,而不是显示每个匹配的行
至于-F,它只是意味着使用一个固定的字符串而不是正则表达式来解释模式。另一个有用的注意事项,属于这里:您可以添加-i或--ignore-case来区分大小写。
-F
-i
--ignore-case
sed "s/[^:]*://"
Source。
| sort | uniq
谁想要重复的路径?不是你,也不是我!哦,嘿,看,它们也被排序了!享受吧。来源:我。我已经用这个只要我能记得。(man sort和man uniq)
man sort
man uniq
xargs basename
你可能会认为| basename可以工作,但不是。它不接受输入标准输入,而是作为命令行参数。下面是an explanation。去图!basename基本上返回没有前导路径的 Backbone.js 文件名。man basename。
| basename
basename
man basename
当然,只需在末尾加上一个realpath。就像这样:
realpath
) | sort | uniq | xargs realpath
当然,你必须使用xargs,因为realpath不使用标准输入作为输入。它使用命令行参数。就像dirname一样。
xargs
dirname
brqmpdu18#
vim-fugitive对于Vim中的这种检查是通用的。使用:Ggrep来完成。有关更多信息,您可以安装vim-fugitive并通过:help Grep查找turorial。这一集:exploring-the-history-of-a-git-repository将指导您完成所有这些操作。
:Ggrep
:help Grep
mftmpeh89#
如果你想搜索敏感数据,以便将其从Git历史记录中删除(这就是我来到这里的原因),有一些工具可以做到这一点。GitHub作为a dedicated help page for that issue。以下是文章的要点:BFG Repo-Cleaner是git filter-branch移除不需要的数据的更快、更简单的替代方法。例如,要移除包含敏感数据的文件并保持最新提交不变,请运行:
bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA
要替换passwords.txt中列出的所有文本,无论它在存储库历史记录中位于何处,请运行:
bfg --replace-text passwords.txt
请参阅BFG Repo-Cleaner's documentation了解完整的使用和下载说明。
9条答案
按热度按时间5ktev3wc1#
如果你想找到所有的提交,其中 commit message 包含一个给定的单词,使用
如果你想找到所有在 file contents 中添加或删除了“word”的提交(更确切地说:其中“word”的出现次数改变),即搜索 * 提交内容 *,使用所谓的“pickaxe”搜索
在现代的Git中也有
查找添加或删除的行与“word”匹配的 * 差异 *(也是 * 提交内容 *)。
需要注意的几点:
-G
默认接受正则表达式,而-S
接受字符串,但可以使用--pickaxe-regex
修改它以接受正则表达式。-S
查找“word”出现次数发生变化的提交,而-G
查找“word”出现在diff中的提交。-S<regex> --pickaxe-regex
和-G<regex>
做的事情并不完全相同。git diff
documentation有一个很好的解释:为了说明
-S<regex> --pickaxe-regex
和-G<regex>
之间的区别,考虑在同一个文件中具有以下差异的提交:虽然
git log -G"frotz\(nitfol"
将显示此提交,但git log -S"frotz\(nitfol" --pickaxe-regex
不会(因为该字符串的出现次数没有改变)。这将显示包含搜索词的提交,但如果你想看到这些提交中的实际变化,你可以使用
--patch
:然后可以将其通过管道传输到
grep
,以隔离输出,只显示带有该搜索词的提交差异行。一个常见的用例是显示自提交以来并包括给定提交(在本示例中为3b5ab0f2a1
)的带有该搜索词的提交差异行,如下所示:nbysray52#
git log
的pickaxe将找到包含“word”的修改的提交ymdaylpp3#
经过大量的实验,我可以推荐以下内容,它显示了引入或删除包含给定regexp的行的提交,并显示了每个提交中的文本更改,并用颜色显示了添加和删除的单词。
虽然需要一段时间才能运行…;- )
vxf3dgd44#
另一种方法/语法是:
git log -S "word"
这样你可以搜索例如
git log -S "with whitespaces and stuff @/#ü !"
mtb9vblg5#
您可以尝试以下命令:
或者按以下方式使用
grep
:在要搜索的父目录中运行此命令。
iyfjxgzm6#
要在正则表达式上使用布尔连接符,请执行以下操作:
此正则表达式在提交消息中搜索正则表达式[0-9]* 或[a-z]*。
2ic8powd7#
这在与BFG(Git过滤器分支-不要与 * git-filter-branch * 混淆)和git-filter-repo结合使用时非常有用。它只是获取文件路径,以便您可以将它们提供给我刚才提到的两个工具之一。
A.相对、唯一、排序、路径:
B.唯一、排序、文件名(不是路径):
第二个命令对BFG很有用,因为它只接受文件名,而不接受repo-relative/system-absolute路径。
好了。享受使用这些Bash片段给我带来的痛苦吧。我讨厌Bash,那我为什么还要继续使用它呢?
解剖
仅获取文件名/路径
以下任何一个选项的含义都是相同的(git-rep文档):
-l
--files-with-matches
--name-only
只显示包含Blockquote的文件的名称,而不是显示每个匹配的行
是您的模式:A.正则表达式v.s. B.固定字符串?
至于
-F
,它只是意味着使用一个固定的字符串而不是正则表达式来解释模式。另一个有用的注意事项,属于这里:您可以添加
-i
或--ignore-case
来区分大小写。去掉那个愚蠢的前导提交哈希
Source。
获取唯一路径!
谁想要重复的路径?不是你,也不是我!哦,嘿,看,它们也被排序了!享受吧。
来源:我。我已经用这个只要我能记得。(
man sort
和man uniq
)没有路径的文件名怎么办?
你可能会认为
| basename
可以工作,但不是。它不接受输入标准输入,而是作为命令行参数。下面是an explanation。去图!basename
基本上返回没有前导路径的 Backbone.js 文件名。man basename
。对于方法A,我希望绝对路径而不是相对路径。
当然,只需在末尾加上一个
realpath
。就像这样:当然,你必须使用
xargs
,因为realpath
不使用标准输入作为输入。它使用命令行参数。就像dirname
一样。灵感
brqmpdu18#
vim-fugitive对于Vim中的这种检查是通用的。
使用
:Ggrep
来完成。有关更多信息,您可以安装vim-fugitive并通过:help Grep
查找turorial。这一集:exploring-the-history-of-a-git-repository将指导您完成所有这些操作。mftmpeh89#
如果你想搜索敏感数据,以便将其从Git历史记录中删除(这就是我来到这里的原因),有一些工具可以做到这一点。GitHub作为a dedicated help page for that issue。
以下是文章的要点:
BFG Repo-Cleaner是git filter-branch移除不需要的数据的更快、更简单的替代方法。例如,要移除包含敏感数据的文件并保持最新提交不变,请运行:
要替换passwords.txt中列出的所有文本,无论它在存储库历史记录中位于何处,请运行:
请参阅BFG Repo-Cleaner's documentation了解完整的使用和下载说明。