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

它们的典型场景是什么?


概念上的区别是:

With git submodules you typically want to separate a large repository into smaller ones. The way of referencing a submodule is maven-style - you are referencing a single commit from the other (submodule) repository. If you need a change within the submodule you have to make a commit/push within the submodule, then reference the new commit in the main repository and then commit/push the changed reference of the main repository. That way you have to have access to both repositories for the complete build.

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


Submodule更适合于基于组件的开发,在这种情况下,您的主项目依赖于另一个组件(repo)的固定版本。 只在父repo中保留引用(gitlinks,索引中的特殊条目)

如果我想链接总是指向外部回购的HEAD怎么办?

你可以让一个子模块遵循子模块远程回购分支的HEAD,使用:

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


Subtree更像是一个基于系统的开发,其中所有的repo一次包含所有内容,您可以修改任何部分。 请看这个答案中的一个例子。

另外,正如philb在评论中指出的那样,git子树是一个contrib/,而不是git子模块(core command)


子模块为link;

子树是复制的


sub-module 将主repo推到远程不会推子模块的文件

子树 将主repo推到远程可以推子树的文件


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