什么时候使用git子树?

时间:2015-09-04 22:54:02

标签: git git-subtree

git subtree解决了什么问题? 何时以及为何要使用该功能?

我读过它是used for repository separation。但为什么我不只是创建两个独立的存储库而不是将两个不相关的存储库合二为一?

这个GitHub教程解释了how to perform Git subtree merges

我知道如何使用它,但 (用例)和为什么,以及它与{{ 3}}。当我依赖于另一个项目或库时,我会使用子模块。

5 个答案:

答案 0 :(得分:31)

git的上下文中使用术语'子树'时,您应该谨慎地注意到您所说的内容,因为这里实际上有两个独立但相关的主题:

git-subtreegit subtree merge strategy

TL; DR

两个子树相关概念都有效地允许您在一个中管理多个存储库。与git-submodule相比,只有元数据以.gitmodules的形式存储在根存储库中,您必须单独管理外部存储库。

更多详情

git子树合并策略基本上是使用您引用的命令的手动方法。

git-subtree 是一个包装shell脚本,可以提供更自然的语法。这实际上仍然是contrib的一部分,并没有与通常的手册页完全集成到git中。而documentation则存储在脚本旁边。

以下是使用信息:

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>]

我在子树的主题上遇到了相当多的资源,因为我正在计划编写自己的博客文章。如果我这样做,我会更新这篇文章,但现在这里有一些与手头问题相关的信息:

您所寻求的大部分内容都可以在this Atlassian blog Nicola Paolucci下方的相关部分找到:

  

为什么使用子树而不是子模块?

     

有几个原因   您可能会发现subtree更好用:

     
      
  • 简单管理简单的工作流程。
  •   
  • 支持较早版本的git(甚至在v1.5.2之前)。
  •   
  • 在超级项目的clone完成后,子项目的代码可用。
  •   
  • subtree不要求您的存储库用户学习任何新内容,他们可以忽略您使用subtree来管理依赖项的事实。
  •   
  • subtree不会添加submodules之类的新元数据文件(即   .gitmodule)。
  •   
  • 可以在没有a的情况下修改模块的内容   在其他地方单独的依赖存储库副本。
  •   
     

在我看来,这些缺点是可以接受的:

     
      
  • 您必须了解新的合并策略(即subtree)。
  •   
  • 为子项目贡献代码upstream稍微复杂一些。
  •   
  • 在提交中不混合超级和子项目代码的责任在于你。
  •   

我同意其中的大部分内容。我会建议查看文章,因为它有一些常见用法。

你可能已经注意到他还写了一篇跟进here,他在那里提到了一个重要的细节,这种方法被这种方法所取代......

git-subtree目前无法包含遥控器!

这种短视可能是因为人们经常在处理子树时手动添加遥控器,但这也不存储在git中。作者详细介绍了他编写的补丁,用于将此元数据添加到git-subtree已生成的提交中。在进入官方git主线之前,你可以通过修改提交消息或将其存储在另一个提交中来做类似的事情。

我也发现this blog post信息非常丰富。作者添加了第三个子树方法,他将git-stree称为混合。这篇文章值得一读,因为他在比较这三种方法方面做得非常好。他对自己所做的和不喜欢的事情给出了个人意见,并解释了为什么他创造了第三种方法。

附加功能

结束思考

此主题显示git的强大功能以及功能错过商标时可能发生的细分。

我个人已经对git-submodule产生了厌恶,因为我觉得让贡献者更难以理解。我还希望在我的项目中管理所有我的依赖项,以便在不尝试管理多个存储库的情况下实现易于重现的环境。然而,git-submodule目前更为人所知,因此了解它并依赖于您的观众可能会影响您的决定显然是很好的。

答案 1 :(得分:8)

第一个:我相信你的问题往往得到强烈的自以为是的答案,可能在这里被视为偏离主题。但是,我并不喜欢这样的SO政策,并且会把关于主题的边界推向外面,所以我喜欢回答并希望其他人也这样做。

在您指向的GitHub教程中,指向How to use the subtree merge strategy的链接,提供了优缺点的观点:

  

将子树合并与子模块进行比较

     

使用子树合并的好处是需要较少的存储库用户的管理负担。它有效   旧版(在Git v1.5.2之前)客户端,您就拥有了正确的代码   克隆

     

但是,如果您使用子模块,则可以选择不传输子模块对象。这可能是子树合并的问题。

     

此外,如果您对其他项目进行了更改,如果您只使用子模块,则更容易提交更改

以下是我的观点:

我经常与那些不是常规git用户的人(=提交者)合作,有些人仍然(并将永远)与版本控制斗争。教育他们如何使用子模块合并策略基本上是不可能的。它涉及额外遥控器的概念,关于合并,分支,然后将它们全部混合到一个工作流程中。从上游拉出并向上游推进是一个两阶段过程。由于分支很难为他们理解,这都是没有希望的。

对于子模块,它们仍然过于复杂(叹息)但更容易理解:它只是回购中的回购(他们熟悉层次结构)你可以像往常一样进行推拉。

为子模块工作流提供简单的包装脚本更容易。

对于具有许多子回购的大型超级回购,选择不克隆某些子回购数据的点是子模块的一个重要优点。我们可以根据工作要求和磁盘空间使用情况对此进行限制。

访问控制可能不同。 Haven尚未遇到此问题,但如果不同的存储库需要不同的访问控制,有效地禁止某些用户使用某些子存储库,我想知道使用子模块方法是否更容易实现。

就个人而言,我还没有决定自己使用什么。所以我分享你的困惑:o]

答案 2 :(得分:3)

我们在git子树是救赎的真实用例:

我们公司的主要产品是高模块化,并在不同的存储库中的多个项目中开发。所有模块都有各自的路线图。 整个产品由具体版本的所有模块组成。

同时,为每个客户定制整个产品的具体版本 - 每个模块的单独分支。有时必须在多个项目中进行定制(cross-module customization)。

为了为定制产品提供单独的产品生命周期(维护,功能分支),我们引入了git子树。我们为所有自定义模块都有一个git-subtree存储库。我们的定制是日常的“git subree push&#39;返回所有原始存储库到自定义分支。

像这样我们避免管理许多回购和许多分支。 git-subtree多次提高了我们的工作效率!

答案 3 :(得分:1)

基本上Git子树是Git子模块方法的替代方案: 有许多缺点,或者我会说,在使用git-submodules时你需要非常小心。例如,当你有“一个”仓库并且在“一个”里面时,你已经使用子模块添加了另一个名为“两个”的仓库。你需要注意的事情:

  • 当您更改“two”中的内容时,您需要提交并推送到“two”内部,如果您位于顶级目录(即“one”),您的更改将不会突出显示。

  • 当一个未知用户试图克隆你的“一个”仓库时,克隆“一个”用户需要更新子模块以获得“两个”仓库

这些是一些要点,为了更好地理解,我建议您观看此视频:https://www.youtube.com/watch?v=UQvXst5I41I&t=576s

  • 为了克服这些问题,发明了子树方法。要获得有关git-subtree的基础知识,请查看以下内容:https://www.youtube.com/watch?v=t3Qhon7burE&t=772s

  • 我发现与子模块相比,子树方法更可靠,更实用:)(我非常初衷地说这些事情)

干杯!

答案 4 :(得分:0)

要添加上述答案,使用子树的另一个缺点是与子模块相比的repo大小。

我没有任何真实世界的指标,但鉴于每次对模块进行推送时,使用该模块的任何地方都会获得父模块上相同更改的副本(随后在这些存储库上更新时) )。

因此,如果代码库经过大量模块化,那么这种代码库会非常快速地增加。

然而,鉴于存储价格总是下降,这可能不是一个重要因素。