何时使用 git 子树?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32407634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use git subtree?
提问by Lernkurve
What problem does git subtree
solve?
When and why should I use that feature?
git subtree
解决什么问题?我何时以及为什么应该使用该功能?
I've read that it is used for repository separation. But why would I not just create two independent repositories instead of sticking two unrelated ones into one?
我读过它用于存储库分离。但是为什么我不只是创建两个独立的存储库,而不是将两个不相关的存储库合二为一呢?
This GitHub tutorial explains how to perform Git subtree merges.
这个 GitHub 教程解释了如何执行 Git 子树合并。
I kind of know howto use it, but not when(use cases) and why, and how it relates to git submodule
. I'd use submodules when I have a dependency on another project or library.
我有点知道如何使用它,但不知道何时(用例)和为什么,以及它与git submodule
. 当我依赖另一个项目或库时,我会使用子模块。
采纳答案by Matthew Sanders
You should be careful to note explicitly what you are talking about when you use the term 'subtree'in the context of git
as there are actually two separate but related topics here:
当您在上下文中使用术语“子树”时,您应该注意明确指出您在说什么,git
因为这里实际上有两个独立但相关的主题:
git-subtreeand git subtree merge strategy.
The TL;DR
TL; DR
Both subtree related concepts effectively allow you to manage multiple repositories in one. In contrast to git-submodulewhere only metadata is stored in the root repository, in the form of .gitmodules, and you must manage the external repositories separately.
这两个与子树相关的概念都有效地允许您将多个存储库合二为一。与git-submodule 相比,只有元数据以.gitmodules的形式存储在根存储库中,您必须单独管理外部存储库。
More Details
更多细节
git subtree merge strategyis basically the more manual method using the commands you referenced.
git subtree 合并策略基本上是使用您引用的命令的更手动的方法。
git-subtreeis a wrapper shell script to facilitate a more natural syntax. This is actually still a part of contrib
and not fully integrated into git with the usual man pages. The documentationis instead stored along side the script.
git-subtree是一个包装壳脚本,以促进更自然的语法。这实际上仍然是contrib
通常的手册页的一部分,并没有完全集成到 git 中。相反,文档与脚本一起存储。
Here is the usage info:
以下是使用信息:
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>]
I have come across a pretty good number of resources on the subject of subtrees, as I was planning on writing a blog post of my own. I will update this post if I do, but for now here is some relevant information to the question at hand:
我遇到了很多关于子树主题的资源,因为我正计划写一篇自己的博客文章。如果我这样做,我会更新这篇文章,但现在这里有一些与手头问题相关的信息:
Much of what you are seeking can be found on this Atlassian blogby Nicola Paoluccithe relevant section below:
您可以在Nicola Paolucci的Atlassian 博客的以下相关部分找到您正在寻找的大部分内容:
Why use subtree instead of submodule?
There are several reasons why you might find
subtree
better to use:
- Management of a simple workflow is easy.
- Older version of
git
are supported (even beforev1.5.2
).- The sub-project's code is available right after the
clone
of the super project is done.subtree
does not require users of your repository to learn anything new, they can ignore the fact that you are usingsubtree
to manage dependencies.subtree
does not add new metadata files likesubmodules
does (i.e..gitmodule
).- Contents of the module can be modified without having a separate repository copy of the dependency somewhere else.
In my opinion the drawbacks are acceptable:
- You must learn about a new merge strategy (i.e.
subtree
).- Contributing code back
upstream
for the sub-projects is slightly more complicated.- The responsibility of not mixing super and sub-project code in commits lies with you.
为什么使用子树而不是子模块?
您可能会发现
subtree
更好用的原因有几个:
- 管理简单的工作流程很容易。
git
支持旧版本的(甚至之前v1.5.2
)。- 子项目的代码
clone
在超级项目完成后立即可用。subtree
不需要存储库的用户学习任何新东西,他们可以忽略您subtree
用于管理依赖项的事实。subtree
不像submodules
(即.gitmodule
)那样添加新的元数据文件。- 可以修改模块的内容,而无需在其他地方拥有依赖项的单独存储库副本。
在我看来,缺点是可以接受的:
- 您必须了解新的合并策略(即
subtree
)。upstream
为子项目贡献代码稍微复杂一些。- 不在提交中混合超级和子项目代码的责任在于您。
I would agree with much of this as well. I would recommend checking out the article as it goes over some common usage.
我也同意这一点。我建议查看这篇文章,因为它介绍了一些常见用法。
You may have noticed that he has also written a follow up herewhere he mentions an important detail that is left off with this approach...
您可能已经注意到,他还在这里写了一篇后续文章,其中提到了这种方法遗漏的一个重要细节......
git-subtree
currently fails to include the remote!
git-subtree
目前无法包括遥控器!
This short sightedness is probably due to the fact that people often add a remote manually when dealing with subtrees, but this isn't stored in git either. The author details a patch he has written to add this meta data to the commit that git-subtree
already generates. Until this makes it into the official git mainline you could do something similar by modifying the commit message or storing it in another commit.
这种短视可能是由于人们在处理子树时经常手动添加遥控器,但这也没有存储在 git 中。作者详细说明了他编写的一个补丁,将这个元数据添加到git-subtree
已经生成的提交中。在它进入官方 git 主线之前,您可以通过修改提交消息或将其存储在另一个提交中来做类似的事情。
I also find this blog postvery informative as well. The author adds a third subtree method he calls 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-stree
。这篇文章值得一读,因为他在比较三种方法方面做得非常好。他对自己喜欢什么和不喜欢什么给出了他的个人意见,并解释了为什么他创造了第三种方法。
Extras
附加功能
Closing Thoughts
闭幕式
This topic shows both the power of git
and the segmentation that can occur when a feature just misses the mark.
本主题展示了git
当特征未达标时可能发生的分割的力量和分割。
I personally have built a distaste for git-submodule
as I find it more confusing for contributors to understand. I also prefer to keep ALLof my dependencies managed within my projects to facilitate an easily reproducible environment without trying to manage multiple repositories. git-submodule
, however, is much more well known currently so it is obviously good to be aware of it and depending on your audience that may sway your decision.
我个人对它产生了厌恶,git-submodule
因为我发现贡献者更难以理解。我也更喜欢在我的项目中管理我的所有依赖项,以促进易于重现的环境,而无需尝试管理多个存储库。git-submodule
但是,目前更广为人知,因此了解它并取决于可能会影响您的决定的观众显然是件好事。
回答by cfi
First of: I believe your question tends to get strongly opinionated answers and may be considered off-topic here. However I don't like that SO policy and would push the border of being on-topic a bit outward, so I like to answer instead and hope others do as well.
首先:我相信你的问题往往会得到强烈的自以为是的答案,在这里可能会被认为是题外话。但是,我不喜欢那个 SO 政策,并且会将话题的边界推向外部,所以我喜欢回答并希望其他人也这样做。
On the GitHub tutorial that you pointed to there's a link to How to use the subtree merge strategywhich gives a viewpoint on advantages/disadvantages:
在您指向的 GitHub 教程中,有一个指向如何使用子树合并策略的链接,该链接提供了有关优点/缺点的观点:
Comparing subtree merge with submodules
The benefit of using subtree mergeis that it requires less administrative burden from the usersof your repository. It works with older(before Git v1.5.2) clientsand you have the code right after clone.
However if you use submodulesthen you can choose not to transfer the submodule objects. This may be a problem with the subtree merge.
Also, in case you make changes to the other project, it is easier to submit changesif you just use submodules.
比较子树合并与子模块
使用子树合并的好处是它需要更少的存储库用户的管理负担。它适用于较旧的(在 Git v1.5.2 之前)客户端,并且您在克隆后立即拥有代码。
但是,如果您使用子模块,那么您可以选择不传输子模块对象。这可能是子树合并的问题。
此外,如果您对其他项目进行更改,如果您只使用子模块,则提交更改会更容易。
Here's my viewpoint based on the above:
基于以上,我的观点如下:
I often work with folks (=committers) who are no regular git users, some still (and will forever) struggle with version control. Educating them about how to use the submodule merge strategy is basically impossible. It involves the concepts of additional remotes, about merging, branches, and then mixing it all into one workflow. Pulling from upstream and pushing upstream is a two stage process. Since branches is difficult to understand for them, this is all hopeless.
我经常与不是常规 git 用户的人(=提交者)一起工作,有些人仍然(并将永远)在版本控制方面挣扎。教育他们如何使用子模块合并策略基本上是不可能的。它涉及附加遥控器的概念,关于合并、分支,然后将其全部混合到一个工作流程中。从上游拉动和推向上游是一个两阶段的过程。由于分支对他们来说很难理解,这一切都是无望的。
With submodules it's still too complicated for them (sigh) but it is easier to understand: It's just a repo within a repo (they are familiar with hierarchy) and you can do your pushing and pulling as usual.
对于子模块,它对他们来说仍然太复杂(叹气),但更容易理解:它只是一个 repo 中的一个 repo(他们熟悉层次结构),您可以像往常一样进行推拉。
Providing simple wrapper scripts is easier imho for the submodule workflow.
恕我直言,为子模块工作流程提供简单的包装器脚本更容易。
For large super-repos with many sub-repos the point of choosing not to clone data of some sub-repos is an important advantage of the submodules. We can limit this based on work requirements and disk space usage.
对于具有许多子存储库的大型超级存储库,选择不克隆某些子存储库的数据是子模块的一个重要优势。我们可以根据工作要求和磁盘空间使用情况对此进行限制。
Access control might be different. Haven't had this issue yet, but if different repos require different access controls, effectively banning some users from some sub-repos, I wonder if that's easier to accomplish with the submodule approach.
访问控制可能不同。还没有遇到这个问题,但是如果不同的 repos 需要不同的访问控制,有效地禁止某些用户进入某些 sub-repos,我想知道使用 submodule 方法是否更容易完成。
Personally I'm undecided what to use myself. So I share your confusion :o]
就我个人而言,我还没有决定自己使用什么。所以我分享你的困惑:o]
回答by Marek Jagielski
A real use case that we have where git subtree was a salvation:
我们有一个真实的用例,其中 git subtree 是一种救赎:
The main product of our company is high modular and developed in several projects in separate repositories. All modules have their separate roadmap. Whole product is composed with all modules of concrete versions.
我们公司的主要产品是高度模块化的,并在不同的存储库中的多个项目中开发。所有模块都有各自的路线图。整个产品由具体版本的所有模块组成。
In parallel the concrete version of whole product is customized for each of our clients - seperate branches for each module. Customization have to be made sometimes in several project at once (cross-module customization
).
与此同时,整个产品的具体版本是为我们的每个客户定制的——每个模块都有单独的分支。有时必须同时在多个项目中进行定制 ( cross-module customization
)。
To have a separate product life cycle (maintenance, feature branches) for customized product we introduced git subtree. We have one git-subtree repository for all customized modules. Our customization are everyday 'git subtree push' back to all original repositories to customization branches.
为了为定制产品提供单独的产品生命周期(维护、功能分支),我们引入了 git subtree。我们有一个用于所有自定义模块的 git-subtree 存储库。我们的定制是每天“git subtree push”回到所有原始存储库到定制分支。
Like this we avoid managing many repos and many braches. git-subtree increased our productivity several times!
像这样,我们避免管理许多 repos 和许多分支。git-subtree 数倍地提高了我们的生产力!
UPDATE
更新
More details about solution that was posted to comments:
有关发布到评论的解决方案的更多详细信息:
We created a brand new repository. Then we added each project that had client branch to that new repo as subtree. We had a jenkins job that was pushing back master changes to original repositories to client branch regularly. We worked just with "client repo" using tipical git flow with feature and maintenance branches.
我们创建了一个全新的存储库。然后我们将每个具有客户端分支的项目作为子树添加到该新存储库中。我们有一个 jenkins 工作,定期将原始存储库的主更改推送到客户端分支。我们只使用带有功能和维护分支的典型 git 流来处理“客户端存储库”。
Our 'client' repo had also building scripts that we also adapted for this particular client.
我们的“客户”存储库还构建了我们也为这个特定客户改编的脚本。
However there is a pitfall of presented solution.
然而,提出的解决方案存在缺陷。
As we were going farther and farther from the main core development of product the possible upgrade for that particular client was more and more difficult. In our case it was ok as the state of project before subtree had been already far a way of main path, so the subtree introduce at least order and possibility to introduce default git flow.
随着我们离产品的主要核心开发越来越远,那个特定客户可能的升级变得越来越困难。在我们的例子中,子树之前的项目状态已经是一条主路径,所以子树至少引入了引入默认 git 流程的顺序和可能性。
回答by SH'
Basically Git-subtree are the alternatives for the Git-submodule approach: There are many drawbacks or rather I would say, you need to be very careful while using git-submodules. e.g when you have "one" repo and inside "one" you have added another repo called "two" using submodules. Things you need to take care:
基本上 Git-subtree 是 Git-submodule 方法的替代方案:有很多缺点,或者我想说的是,在使用 git-submodules 时你需要非常小心。例如,当您有“一个”存储库并且在“一个”内部时,您使用子模块添加了另一个名为“两个”的存储库。您需要注意的事项:
When you change something in "two", you need to commit and push inside "two", if you are at top-level directory (i.e in "one") your changes wont get highlighted.
When an unknown user tries to clone your "one" repo, after cloning "one" that user needs to update the submodules to get the "two" repo
当您在“two”中更改某些内容时,您需要提交并推送到“two”中,如果您位于顶级目录(即在“one”中),则您的更改不会突出显示。
当未知用户尝试克隆您的“一个”存储库时,在克隆“一个”之后,该用户需要更新子模块以获取“两个”存储库
These are some of the points and for better understanding I would recommend you to watch this video: https://www.youtube.com/watch?v=UQvXst5I41I
这些是一些要点,为了更好地理解,我建议您观看此视频:https: //www.youtube.com/watch?v=UQvXst5I41I
To overcome such problems subtree approach is invented. To get the basics about git-subtree, have a view on this: https://www.youtube.com/watch?v=t3Qhon7burE
I find subtree approach is more reliable and practical compare to submodules :) (I am very much beginner to say these things)
为了克服这些问题,发明了子树方法。要获得有关 git-subtree 的基础知识,请查看以下内容:https: //www.youtube.com/watch?v=t3Qhon7burE
我发现与子模块相比,子树方法更可靠和实用:)(我非常初学者说这些事情)
Cheers!
干杯!
回答by Paul Phillips
To add to above answers, an additional drawback of using subtree is the repo size compared to submodules.
要补充上述答案,与子模块相比,使用子树的另一个缺点是存储库大小。
I don't have any real world metrics, but given that each time a push is made on a module, everywhere that module is used gets a copy of the same change on the parent module (when is subsequently updated on those repos).
我没有任何现实世界的指标,但考虑到每次对模块进行推送时,使用该模块的任何地方都会在父模块上获得相同更改的副本(随后在这些存储库上更新时)。
So if a code base is heavily modularised, that will add up quite quickly.
因此,如果代码库是高度模块化的,那么加起来会很快。
However, given storage prices are always coming down, that may not be a significant factor.
然而,鉴于存储价格总是在下降,这可能不是一个重要因素。