如何在根目录上列出 Git 子树?

53
例如,您可以执行git remote --verbose命令,Git将显示项目中所有远程引用的详细信息;git branch命令将显示所有分支并标识当前所在分支。但是,如何列出所有子树而不使用任何破坏性命令?git subtree将提供用法示例,但不会列出任何内容。subtree只有添加(add)、拉取(pull)、推送(push)、拆分(split)和合并(merge)等命令。

1
请问什么是子树?运行 git subtree 后出现 git: 'subtree' is not a git command. - Jokester
1
你需要单独安装subtree,它目前不随git捆绑安装。http://engineeredweb.com/blog/how-to-install-git-subtree/ 。subtree是submodule的更好替代品 :) - pocesar
1
@pocesar git subtree已经合并到主线git中,并且自版本1.7.11以来一直可用。 - 1615903
确实,但一些Git版本(例如上面@jokester提到的)没有附带它。我在Windows上使用msysgit 1.8.2.1,它已经包含了它 :) - pocesar
嗯...我刚刚从源代码构建了1.8.4版本以获取最新版本,但它仍然说'subtree'不是git命令。我的“git --version”显示:git version 1.8.4.rc1.4.gd6cbf2f - Stabledog
谜团解开了:仅仅构建git还不够,您还需要构建contrib/subtree(那里有一个INSTALL文件)。否则,即使是最新的git也会抱怨'subtree'不是一个有意义的命令。 - Stabledog
4个回答

72

目前没有明确的方法来做到这一点,唯一可用的命令在此处列出(正如您自己注意到的那样,但这里提供了未来寻求者的参考链接): https://github.com/git/git/blob/master/contrib/subtree/git-subtree.txt

我已经查阅了代码(基本上所有机制都是一个大的shell脚本文件),所有的跟踪都是通过提交消息完成的,因此所有函数都使用 git log 机制并进行大量的 grep 操作来定位它自己的数据。

由于子树必须具有与存储库根文件夹相同的名称,因此您可以运行以下命令(在Bash shell中)以获取所需的信息:

git log | grep git-subtree-dir | tr -d ' ' | cut -d ":" -f2 | sort | uniq

现在,这个方法并不检查文件夹是否存在(你可能已经把它删除了而子目录机制并不知道),因此以下是如何仅列出现有子树的方法,这将适用于存储库中的任何文件夹:

 git log | grep git-subtree-dir | tr -d ' ' | cut -d ":" -f2 | sort | uniq | xargs -I {} bash -c 'if [ -d $(git rev-parse --show-toplevel)/{} ] ; then echo {}; fi'

如果你真的有兴趣,建议向 Git 的开发者们提出在未来版本中包含它 :)


1
你给出的命令对我不起作用。git log | grep git-subtree-dir没有返回任何结果(git版本1.7.9.5)。 - FlipMcF
3
+1. @procesar,FlipMcF:这对我在Windows上的“git bash”中有效:“git版本1.8.5.2.msysgit.0”。它应该有效是因为“git subtree”命令会在提交消息中添加几行以“git-subtree-”开头的内容,其中一行看起来像“git-subtree-dir:you-prefix-folder”。至于“prof”,只需在运行“git subtree add ...”后立即查看“git log”的输出,就会看到这些行。 - Eddy Shterenberg
1
@FlipMcF,官方子树支持在1.7.11中被添加,所以我猜你正在使用旧的和分离的子树模块,这不适用于现代版本。你可以安装最新的子树脚本(参见此处),或升级你整个git安装。 - Sagi Iltus
很酷,很高兴我们能帮到你 :) - Sagi Iltus
1
更强大的版本是 git log --format=%b | awk '/git-subtree-dir/{ print $NF }' | sort --unique,当 git config core.format[.pretty] 设置为不显示提交信息 %b 时。 - Daniel Bayley
显示剩余5条评论

36

在跟进Sagi Illtus的回答(来源)后,将以下别名添加到您的~/.gitconfig文件中

[alias]
    ls-subtrees = !"git log | grep git-subtree-dir | awk '{ print $2 }'"

你可以从你的代码库根目录下运行 git ls-subtrees 命令来展示所有子树路径:

$> cd /path/to/repository
$> git ls-subtrees
some/subtree/dir

这很棒,但它在我的存储库中会输出重复项 - 可能是因为我已经添加了删除和重新添加子树。当我真正知道自己在做什么时,这将非常有帮助;-) - user1645942
2
@MattBracewell 看一下 uniq。你可以更新别名以将其管道传输到它,或者使用 git ls-subtrees|uniq - kenchilada
4
可以使用sort -u命令,并且作为额外加分项,可以按字母顺序排列目录! - Potherca
不需要调用 grep[alias] subtree-list = !git log --format=%b | awk '/git-subtree-dir/{ print $NF }' | sort --unique - Daniel Bayley

4
在日志中使用grep的问题在于,它并不告诉你子目录是否仍然存在。我通过简单地测试目录的存在来解决这个问题:
[alias]
        ls-subtrees = !"for i in $(git log | grep git-subtree-dir | sed -e 's/^.*: //g' | uniq); do test -d $i && echo $i; done"

0

请查看subrepo。它解决了使用“本地”git子树命令时的缺点。这些缺点是由于git不存储子树的原始存储库URL所致。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接