如何在 Git 分支中搜索文件或目录?

Posted

技术标签:

【中文标题】如何在 Git 分支中搜索文件或目录?【英文标题】:How can I search Git branches for a file or directory? 【发布时间】:2010-09-27 05:09:48 【问题描述】:

在 Git 中,我如何通过多个分支的路径搜索文件或目录?

我在一个分支中写了一些东西,但我不记得是哪一个。现在我需要找到它。

澄清:我正在寻找我在我的一个分支上创建的文件。我想通过路径而不是内容来找到它,因为我不记得内容是什么了。

【问题讨论】:

我不清楚这个问题。此文件是否在现在已删除的分支中?文件被删除了吗? 【参考方案1】:

git log + git branch 会为您找到它:

% git log --all -- somefile

commit 55d2069a092e07c56a6b4d321509ba7620664c63
Author: Dustin Sallings <dustin@spy.net>
Date:   Tue Dec 16 14:16:22 2008 -0800

    added somefile


% git branch -a --contains 55d2069
  otherbranch

也支持通配符:

% git log --all -- '**/my_file.png'

单引号是必需的(至少在使用 Bash shell 时),因此 shell 将 glob 模式原封不动地传递给 git,而不是扩展它(就像 Unix find 一样)。

【讨论】:

如果您知道somefile 的确切路径,则此方法有效:例如,如果您需要对路径/文件名进行正则表达式搜索,则可以使用 ididak 的答案。 也支持通配符:git log --all -- **/my_file.png 我用它来解决一个稍微不同的问题。我试图找到我提交给特定分支的所有 *.sql 文件。所以我使用了git log --grep='branch' --author='me' -- *.sql。像魅力一样工作。 git 版本 1.7.11.1 请注意gitk 也支持通配。这是一个很好的答案@webmat!如果你想查看它在哪里被删除/创建/等,你可以使用git log --all --stat -- **/my_file.png,这样你就不必猜测你是否从删除它的提交中检出它。 @webmat:我冒昧地将您有关 globbing 的信息添加到答案中。感谢您提及!【参考方案2】:

git ls-tree 可能会有所帮助。搜索所有现有分支:

for branch in `git for-each-ref --format="%(refname)" refs/heads`; do
  echo $branch :; git ls-tree -r --name-only $branch | grep '<foo>'
done

这样做的好处是您还可以使用正则表达式搜索文件名。

【讨论】:

一些希望对您有所帮助的 cmets: (a) 您可能希望将“-r”添加到“git ls-tree”,这样即使文件位于子目录中,它也能找到该文件。 (b) 可能比第一行更简洁的替代方法是使用“git for-each ref”,例如"for branch in git for-each-ref --format="%(refname)" refs/heads; do" (c) "git ls-tree --name-only" 将使输出更整洁 (d) 在您的回答中可能值得指出的是,与达斯汀的解决方案相比,这有一个优势,即您不需要确切知道文件名 - 您可以通过匹配路径任何部分的正则表达式进行搜索 我把它封装在一个脚本中,这样你就可以运行 "gitfind.sh ";要点是gist.github.com/62d981890eccb48a99dc 请注意,这只会搜索 local 分支。要搜索远程跟踪分支,请使用 refs/remotes 而不是 refs/heads。要搜索所有内容(本地分支、远程跟踪分支和标签),只需使用 refs/【参考方案3】:

虽然ididak's response 很酷,并且Handyman5 提供了一个脚本来使用它,但我发现使用这种方法有点受限。

有时您需要搜索可以随时间出现/消失的内容,那么为什么不搜索所有提交呢?除此之外,有时你需要一个详细的响应,而其他时候只提交匹配。以下是这些选项的两个版本。将这些脚本放在您的路径上:

git-find-file

for branch in $(git rev-list --all)
do
  if (git ls-tree -r --name-only $branch | grep --quiet "$1")
  then
     echo $branch
  fi
done

git-find-file-verbose

for branch in $(git rev-list --all)
do
  git ls-tree -r --name-only $branch | grep "$1" | sed 's/^/'$branch': /'
done

现在你可以做

$ git find-file <regex>
sha1
sha2

$ git find-file-verbose <regex>
sha1: path/to/<regex>/searched
sha1: path/to/another/<regex>/in/same/sha
sha2: path/to/other/<regex>/in/other/sha

看到使用getopt,您可以修改该脚本以交替搜索所有提交、参考、参考/头、冗长等。

$ git find-file <regex>
$ git find-file --verbose <regex>
$ git find-file --verbose --decorated --color <regex>

结帐https://github.com/albfan/git-find-file 以了解可能的实现。

【讨论】:

你的意思是“现在你可以做 git-find-file ”了吗?我搞定了,谢谢! 我个人觉得使用 $(git branch | cut -c 3-) 代替 $(git rev-list --all) 更有用。我不关心找到一堆提交,我关心命名分支。 我还更改了脚本以使用 $(git branch | cut -c 3-) 因为所有提交的循环太慢了。 看到了所有的大惊小怪,我值得为此创建一个 repo。 github.com/albfan/git-find-file。我已经打开了一些问题,请随时提出更多建议或发送 PR。 @lumbric 在路径上安装脚本开箱即用,它是一个 git 功能【参考方案4】:

您可以使用gitk --all 并搜索提交“接触路径”和您感兴趣的路径名。

【讨论】:

如上所述,使用 gitk --all,然后在 View |新视图,启用所有分支。然后设置您的搜索条件:倒数第二个字段中的文件名(带有通配符)。最后:好的。【参考方案5】:

复制并粘贴此内容以使用git find-file SEARCHPATTERN

打印所有搜索到的分支:

git config --global alias.find-file '!for branch in `git for-each-ref --format="%(refname)" refs/heads`; do echo "$branch:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; done; :'

只打印带有结果的分支:

git config --global alias.find-file '!for branch in $(git for-each-ref --format="%(refname)" refs/heads); do if git ls-tree -r --name-only $branch | grep "$1" > /dev/null; then  echo "$branch:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; fi; done; :'

这些命令会将一些最小的 shell 脚本作为global git alias 直接添加到您的~/.gitconfig

【讨论】:

只在master分支中搜索 搜索所有本地分支机构 如何让它搜索所有本地和远程分支?【参考方案6】:

可以在这里找到用于 Git 存储库的 find 命令的相当不错的实现:

https://github.com/mirabilos/git-find

【讨论】:

以上是关于如何在 Git 分支中搜索文件或目录?的主要内容,如果未能解决你的问题,请参考以下文章

如何搜素git某个分支是否存在?

切换分支时Git不删除文件

如何在 Git 上添加未跟踪的文件?

如何以透明的方式从另一个 git 分支获取目录的副本?

git小技巧--如何从其他分支merge个别文件或文件夹

如何将我当前的更改提交到 Git 中的不同分支 [重复]