git subtree
解决了什么问题?何时以及为什么应该使用该功能?
我读到它是used for repository separation,但是为什么我不创建两个独立的仓库,而不是把两个不相关的仓库放在一个仓库里呢?
这个GitHub教程解释了how to perform Git subtree merges。
我知道如何使用它,但不知道何时使用它(用例)和为什么使用它,以及它与git submodule
的关系。
git subtree
解决了什么问题?何时以及为什么应该使用该功能?
我读到它是used for repository separation,但是为什么我不创建两个独立的仓库,而不是把两个不相关的仓库放在一个仓库里呢?
这个GitHub教程解释了how to perform Git subtree merges。
我知道如何使用它,但不知道何时使用它(用例)和为什么使用它,以及它与git submodule
的关系。
6条答案
按热度按时间7d7tgy0s1#
当你在
git
的上下文中使用术语"子树“**时,你应该小心地明确指出你在谈论什么,因为这里实际上有两个独立但相关的主题:git-subtree和git subtree merge strategy。
TL;DR
与.gitmodules不同的是,git-submodule只将元数据存储在根存储库中,并且必须单独管理外部存储库。
更多详情
git subtree merge strategy基本上是使用你引用的命令的更手动的方法。
git-subtree是一个 Package 器shell脚本,以促进更自然的语法。这实际上仍然是
contrib
的一部分,并没有完全集成到git中。documentation存储在脚本的沿着。以下是使用信息:
字符串
我已经遇到了相当多的关于子树主题的资源,因为我打算写一篇自己的博客文章。如果我这样做,我会更新这篇文章,但现在这里有一些与手头问题相关的信息:
您正在寻找的大部分内容可以在Nicola Paolucci的this Atlassian blog上找到,相关部分如下:
为什么使用子树而不是子模块?
您可能会发现
subtree
更适合用途:git
(甚至在v1.5.2
之前)。clone
完成后立即可用。subtree
不需要你的仓库的用户学习任何新的东西,他们可以忽略你正在使用subtree
来管理依赖项的事实。subtree
不像submodules
那样添加新的元数据文件(即.gitmodule
)。在我看来,缺点是可以接受的:
subtree
)。upstream
稍微复杂一些。我也同意这一点,我建议你看看这篇文章,因为它涉及到一些常见的用法。
您可能已经注意到,他还写了一个后续的here,其中他提到了一个重要的细节,这是与这种方法离开.
git-subtree
当前无法包含远程!这种短视可能是由于人们在处理子树时经常手动添加一个remote,但这也没有存储在git中。作者详细介绍了他编写的一个补丁,用于将此Meta数据添加到
git-subtree
已经生成的提交中。在此补丁成为官方git主线之前,您可以通过修改提交消息或将其存储在另一个提交中来做类似的事情。我也发现this blog post非常有用。作者添加了第三个子树方法,他称之为
git-stree
。这篇文章值得一读,因为他很好地比较了这三种方法。他给出了他个人的观点,他做了什么,不喜欢什么,并解释了为什么他创建了第三种方法。其他
结束语
本主题展示了
git
的强大功能,以及当要素刚好错过标记时可能发生的分割。我个人对
git-submodule
很反感,因为我发现它对贡献者来说更容易理解。我也更喜欢在我的项目中管理所有依赖项,以促进易于复制的环境,而无需尝试管理多个存储库。git-submodule
,然而,目前它更为人所知,因此了解它显然是件好事,并取决于可能影响您决定的受众。67up9zun2#
首先:我相信你的问题往往会得到强烈的固执己见的答案,可能会被认为是偏离主题在这里。但是,我不喜欢这样的政策,并会推动边界的主题有点向外,所以我喜欢回答,而不是希望别人也这样做。
在你提到的GitHub教程中,有一个指向How to use the subtree merge strategy的链接,它给出了关于优点/缺点的观点:
比较子树合并与子模块
使用子树合并的好处是对仓库用户的管理负担更少。它适用于旧版(Git v1.5.2之前)客户端,并且克隆后您就可以获得代码。
但是如果你使用子模块,那么你可以选择不传输子模块对象。这可能是子树合并的问题。
此外,如果您对其他项目进行更改,如果您只使用子模块,则提交更改会更容易。
以下是我基于上述的观点:
我经常和人们一起工作(=committers)不是常规的git用户,有些仍然是(并且将永远)与版本控制作斗争。教育他们如何使用子模块合并策略基本上是不可能的。它涉及到额外远程的概念,关于合并,分支,然后将其混合到一个工作流中。从上游拉取和向上游推送是一个两阶段的过程。由于分支对他们来说很难理解,这一切都毫无希望
对于子模块来说,它仍然太复杂了(* 叹息 *),但它更容易理解:它只是一个repo中的repo(他们熟悉层次结构),你可以像往常一样做你的推拉。
提供简单的 Package 器脚本对于子模块工作流来说更容易。
对于包含许多子存储库的大型超级存储库,选择不克隆某些子存储库的数据是子模块的一个重要优势。我们可以根据工作需求和磁盘空间使用情况限制这一点。
访问控制可能会有所不同。还没有遇到过这个问题,但是如果不同的存储库需要不同的访问控制,有效地班宁一些用户访问一些子存储库,我想知道使用子模块方法是否更容易实现。
就我个人而言,我还没有决定用什么。所以我分享你的困惑:o]
9w11ddsr3#
基本上Git-subtree是Git-submodules方法的替代品:有很多缺点,或者更确切地说,你需要在使用git-submodules时非常小心。例如,当你有“一个”repo,而在“一个”里面,你已经使用子模块添加了另一个名为“两个”的repo。你需要注意的事情:
以下是一些要点,为了更好地理解,我建议您观看此视频:https://www.youtube.com/watch?v=UQvXst5I41I
干杯!干杯!
tvz2xvvm4#
我们有一个真实的用例,其中git subtree是一个救赎:
我们公司的主要产品是高度模块化的,在不同的仓库中的多个项目中开发。所有模块都有自己的路线图。整个产品由具体版本的所有模块组成。
在并行的整个产品的具体版本是定制为我们的每个客户-为每个模块单独的分支。定制有时必须在几个项目一次(
cross-module customization
)。为了让定制产品有一个独立的产品生命周期(维护,功能分支),我们引入了git subtree。我们为所有定制模块提供了一个git subtree存储库。我们的定制是每天'git subtree push'回到所有原始存储库到定制分支。
这样我们就避免了管理许多仓库和分支。git-subtree使我们的生产力提高了好几倍!
更新
有关已发布到评论的解决方案的更多详细信息:
我们创建了一个全新的仓库。然后我们将每个拥有客户端分支的项目作为子树添加到新的仓库中。我们有一个jenkins任务,定期将原始仓库的主更改推回客户端分支。我们使用带有功能和维护分支的tillinggit flow来处理“客户端仓库”。
我们的“客户”仓库也有我们也为这个特定客户改编的构建脚本。
然而,提出的解决方案存在一个缺陷。
随着我们离产品的主要核心开发越来越远,特定客户端的可能升级越来越困难。在我们的情况下,由于子树之前的项目状态已经远离主路径,所以子树至少引入了顺序和可能性来引入默认的git流。
6yt4nkrj5#
为了补充以上答案,使用子树的另一个缺点是与子模块相比的repo大小。
我没有任何真实的世界指标,但考虑到每次对模块进行推送时,使用该模块的任何地方都会在父模块上获得相同更改的副本(随后在这些repos上更新时)。
因此,如果一个代码库是高度模块化的,那么它将很快增加。
然而,考虑到存储价格总是在下降,这可能不是一个重要因素。
dba5bblo6#
我不得不停止使用子模块,因为一个错误,你搞砸了你的回购为自己,和其他人,这是很难修复(“* 哎呀,哪个子模块提交与主代码匹配,我忘记在哪里签入了?* ”)。我得出的结论是,如果git只是默认总是检查整个代码库,包括任何子模块,也可以提交和推送整个代码库,包括子模块,* 除非特别告知不要这样做 *,子模块将非常容易使用。简单地默认将整个嵌套仓库集视为一个大的虚拟仓库(这是默认情况下应该是的,为什么你要包括一个子模块,如果它对项目不是必需的),除非你明确地需要做一些不同的事情,这可能是例外。优化大小,这是git目前所做的,在这个世界上,一个TB的磁盘空间花费$10和很多人有千兆互联网。