git subtree
解决了什么问题?何时以及为什么应该使用该功能?
< p > 我已经阅读过它用于 存储库分离 。但是,我为什么不创建两个独立的存储库,而不是将两个不相关的存储库粘在一起呢?
< p > 这个GitHub教程说明了如何执行Git子树合并。
< p > 我有点了解如何使用它,但不知道何时(用例)和为什么以及它如何与 git submodule
有关。当我依赖另一个项目或库时,我会使用子模块。 (注:已保留HTML标记)
git subtree
解决了什么问题?何时以及为什么应该使用该功能?
< p > 我已经阅读过它用于 存储库分离 。但是,我为什么不创建两个独立的存储库,而不是将两个不相关的存储库粘在一起呢?
< p > 这个GitHub教程说明了如何执行Git子树合并。
< p > 我有点了解如何使用它,但不知道何时(用例)和为什么以及它如何与 git submodule
有关。当我依赖另一个项目或库时,我会使用子模块。 git
的上下文中,实际上有两个不同但相关的主题:git-subtree和git subtree merge strategy。这两个与子树相关的概念都有效地允许您在一个仓库中管理多个仓库。与git-submodule相比,后者只在根仓库中以.gitmodules的形式存储元数据,并且必须单独管理外部仓库。git-subtree 是一个包装的 shell 脚本,用于简化语法。实际上,它仍然是 contrib
的一部分,并未完全集成到 git 中,也没有通常的 man 页面。文档 存储在与脚本相同的位置。
以下是使用信息:
NAME
----
git-subtree - Merge subtrees together and split repository into subtrees
SYNOPSIS
--------
[verse]
'git subtree' add -P <prefix> <commit>
'git subtree' add -P <prefix> <repository> <ref>
'git subtree' pull -P <prefix> <repository> <ref>
'git subtree' push -P <prefix> <repository> <ref>
'git subtree' merge -P <prefix> <commit>
'git subtree' split -P <prefix> [OPTIONS] [<commit>]
我曾经查阅了许多关于子树的资源,因为我计划写一篇博客文章。如果我写了,我会更新这篇文章,但现在这里有一些与问题相关的信息:
你所寻找的很多内容可以在Atlassian博客上找到,由Nicola Paolucci撰写,下面是相关部分:
以下是你可能会发现subtree
更好用的几个原因:
git
(甚至在v1.5.2
之前)。clone
后,子项目的代码就可以使用了。subtree
不需要你的存储库的用户学习任何新知识,他们可以忽略你正在使用subtree
来管理依赖项的事实。subtree
不像submodules
那样添加新的元数据文件(即.gitmodule
)。我认为这些缺点是可以接受的:
subtree
)。我也大部分同意这个观点。建议阅读这篇文章,因为它涵盖了一些常见的用法。
你可能已经注意到他还写了一个这里的跟进文章,在那里他提到了这种方法遗漏的重要细节...
git-subtree
目前未能包含远程仓库!
这种短视可能是因为人们在处理子树时经常手动添加远程仓库,但这也没有存储在git中。作者详细介绍了他编写的补丁,将此元数据添加到git-subtree
已经生成的提交中。在此被合并到官方git主线之前,您可以通过修改提交消息或将其存储在另一个提交中来执行类似操作。
git-stree
to the mix. The article is worth a read as he does a pretty good job of comparing the three approaches. He gives his personal opinion of what he does and doesn't like and explains why he created the third approach.
这个主题展示了git
的强大和当一个功能不能完全满足需求时可能会出现的细分。
git-submodule
并不感冒,因为我认为它更加令贡献者困惑。我也更喜欢在我的项目中管理所有的依赖项,以便于创建一个易于重现的环境,而不需要管理多个存储库。然而,git-submodule
目前更为广泛地使用,所以了解它显然是有好处的,具体是否使用取决于你的受众群体。首先:我认为您的问题很可能会得到强烈的主观答案,并且在这里可能被认为是不相关的。但是我不喜欢SO政策,想要将其边界向外推一点,所以我愿意回答,并希望其他人也这样做。
在您指出的GitHub教程中,有一个链接如何使用子树合并策略,其中提供了优缺点的观点:
以下是我的观点:比较子树合并和子模块
使用子树合并的好处是,它需要用户的管理负担较少。它可以与旧版本(Git v1.5.2之前)客户端一起使用,并且在克隆后就可以获得代码。
然而,如果您使用子模块,则可以选择不传输子模块对象。这可能是子树合并的问题。
此外,如果您对其他项目进行更改,如果只使用子模块,则更容易提交更改。
.backup.<timestamp>
。我认为我在开始时已经表明了这是主观看法。希望其他人能够提供更具事实性的见解,我很惊讶还没有人这样做。 - cfisubmodule
是过时的旧方法,用于合并已使用的库,而 subtree
是新的闪亮方式吗? - Lernkurveread-tree
(以及分支/合并/远程等操作)。submodules
是后来添加的。 - cfi我们公司有一个真实的使用案例,其中git subtree是救星:
我们公司的主要产品是高度模块化的,并在单独的存储库中开发了几个项目。所有模块都有其单独的路线图。整个产品由具体版本的所有模块组成。
与此同时,每个客户的整个产品的具体版本都进行了定制-每个模块都有单独的分支。有时需要在多个项目中同时进行自定义(跨模块自定义)。
为了为定制产品提供单独的生命周期(维护,功能分支),我们引入了git subtree。我们有一个git-subtree存储库用于所有定制模块。我们每天将自定义内容“git subtree push”回所有原始存储库以进行自定义分支。
这样我们就避免了管理许多存储库和许多分支。 git-subtree将我们的生产力提高了数倍!
更新
有关已发布评论的解决方案的更多详细信息:
我们创建了一个全新的存储库。然后,我们将具有客户分支的每个项目作为子树添加到该新存储库中。我们有一个Jenkins工作,定期将主分支更改推回原始存储库以进行客户分支。我们只使用“客户端”存储库,使用典型的git流程进行功能和维护分支。
我们的“客户端”存储库还具有构建脚本,我们还为该特定客户适应了这些脚本。
但是,这种解决方案存在一个陷阱。
随着我们越来越远离产品主要核心开发,对于该特定客户的可能升级变得越来越困难。在我们的情况下,这是可以接受的,因为在子树之前项目的状态已经远离了主路径,因此子树引入了至少一定的顺序和引入默认git流的可能性。
git gc
和ZFS dedup(对象包),子模块具有明显的不公平优势。因此,就存储库大小而言,较小的代码库(而不是存储库计数)应该使用子模块,而较大的代码库应该使用单一存储库。我还没有发现子树的任何用途。 - Tino
submodule
和subtree
都更或多或少实现了相同的目标,即合并相关项目,并且唯一的区别是submodule
可能稍微不太透明,更新子模块是一个两步操作,而subtree
的缺点是提交消息将在两个项目之间混合吗? - Lernkurve子树
的存储库进行二分,并且在依赖项中引入了错误,则可以在子树
中找到引入错误的确切提交。使用子模块,您只会发现导致子模块
版本更新的提交引起了错误,如果您想快速找到在主项目中导致错误的子模块
提交,则有点棘手。 - cyphar