git 子模块和子树之间的区别

Differences between git submodule and subtree

使用 git 子模块和子树在概念上有什么区别?

每个的典型场景是什么?

概念上的区别是:

对于 git 子模块,您通常希望将大型存储库分成较小的存储库。引用子模块的方式是 maven-style - 您正在引用来自其他(子模块)存储库的单个提交。如果您需要在子模块中进行更改,您必须在子模块中进行 commit/push,然后在主存储库中引用新提交,然后 commit/push 主存储库的更改引用。这样你就必须访问两个存储库才能完成构建。

通过 git 子树 您可以将另一个存储库集成到您的存储库中,包括其历史记录。所以在集成它之后,你的存储库的大小可能会更大(所以这不是让存储库变小的策略)。 集成之后,没有与其他存储库的连接,除非您想获得更新,否则您不需要访问它。所以这个策略更多的是为了代码和历史重用——我个人不使用它。

  • submodule 更适合 component-based development,其中您的主项目依赖于另一个组件 (repo) 的固定版本。
    您只在父存储库中保留引用 (gitlinks, special entries in the index)

What if I want the links to always point to the HEAD of the external repo?

您可以使子模块跟随子模块远程仓库分支的 HEAD,使用:

o git submodule add -b <branch> <repository> [<path>]。 (指定要遵循的分支)
o git submodule update --remote 这会将子模块的内容从 <repository>/<branch> 更新到最新的 HEAD,默认情况下 origin/master。即使使用 --remote,您的主项目仍将跟踪子模块 HEAD 的哈希值。


  • subtree 更像是一个 system-based development,你的所有 repo 一次包含所有内容,你可以修改任何部分。
    See an example in this answer.

另外,philb in , git subtree 指出的是 contrib/,而不是 git submodule(核心命令)

子模块是 link;

子树是副本

子模块
将主仓库推送到远程不会推送子模块的文件

子树
将主仓库推送到远程推送子树的文件

考虑子树和子模块的最简单方法是,子树是拉入父存储库的存储库副本,而子模块是指向另一个存储库中特定提交的指针。