你什么时候会使用不同的 git 合并策略?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/366860/
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 would you use the different git merge strategies?
提问by Otto
From the man page on git-merge, there are a number of merge strategies you can use.
在 git-merge 的手册页中,您可以使用多种合并策略。
resolve- This can only resolve two heads (i.e. the current branch and another branch you pulled from) using 3-way merge algorithm. It tries to carefully detect criss-cross merge ambiguities and is considered generally safe and fast.
recursive- This can only resolve two heads using 3-way merge algorithm. When there are more than one common ancestors that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mis-merges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this can detect and handle merges involving renames. This is the default merge strategy when pulling or merging one branch.
octopus- This resolves more than two-head case, but refuses to do complex merge that needs manual resolution. It is primarily meant to be used for bundling topic branch heads together. This is the default merge strategy when pulling or merging more than one branches.
ours- This resolves any number of heads, but the result of the merge is always the current branch head. It is meant to be used to supersede old development history of side branches.
subtree- This is a modified recursive strategy. When merging trees A and B, if B corresponds to a subtree of A, B is first adjusted to match the tree structure of A, instead of reading the trees at the same level. This adjustment is also done to the common ancestor tree.
解析- 这只能使用 3 路合并算法解析两个头(即当前分支和您从中拉出的另一个分支)。它试图仔细检测交叉合并的歧义,通常被认为是安全和快速的。
递归- 这只能使用 3 路合并算法解决两个头。当有多个共同祖先可用于 3 路合并时,它会创建一个共同祖先的合并树,并将其用作 3 路合并的参考树。据报道,通过对取自 Linux 2.6 内核开发历史的实际合并提交进行的测试,这会导致更少的合并冲突,而不会导致错误合并。此外,这可以检测和处理涉及重命名的合并。这是拉取或合并一个分支时的默认合并策略。
octopus- 这解决了两个以上的情况,但拒绝进行需要手动解决的复杂合并。它主要用于将主题分支头捆绑在一起。这是拉取或合并多个分支时的默认合并策略。
ours- 这可以解析任意数量的头,但合并的结果始终是当前的分支头。它旨在用于取代旧的侧枝发展历史。
subtree- 这是一种修改后的递归策略。合并树 A 和 B 时,如果 B 对应于 A 的子树,则首先调整 B 以匹配 A 的树结构,而不是读取同一级别的树。对共同祖先树也进行了这种调整。
When should I specify something different than the default? What scenarios are each best for?
我什么时候应该指定与默认值不同的东西?每个场景最适合什么场景?
采纳答案by Dustin
I'm not familiar with resolve, but I've used the others:
我不熟悉决心,但我使用过其他人:
Recursive
递归
Recursive is the default for non-fast-forward merges. We're all familiar with that one.
递归是非快进合并的默认值。我们都很熟悉那个。
Octopus
章鱼
I've used octopus when I've had several trees that needed to be merged. You see this in larger projects where many branches have had independent development and it's all ready to come together into a single head.
当我有几棵树需要合并时,我使用了章鱼。您可以在较大的项目中看到这一点,在这些项目中,许多分支都进行了独立开发,并且已经准备好整合到一个单一的头部。
An octopus branch merges multiple heads in one commit as long as it can do it cleanly.
章鱼分支在一次提交中合并多个头,只要它可以干净地完成。
For illustration, imagine you have a project that has a master, and then three branches to merge in (call them a, b, and c).
例如,假设您有一个项目,它有一个 master,然后有三个要合并的分支(称为 a、b 和 c)。
A series of recursive merges would look like this (note that the first merge was a fast-forward, as I didn't force recursion):
一系列递归合并看起来像这样(请注意,第一次合并是快进的,因为我没有强制递归):
However, a single octopus merge would look like this:
但是,单个章鱼合并看起来像这样:
commit ae632e99ba0ccd0e9e06d09e8647659220d043b9
Merge: f51262e... c9ce629... aa0f25d...
Ours
我们的
Ours == I want to pull in another head, but throw away all of the changes that head introduces.
我们的 == 我想拉另一个脑袋,但扔掉脑袋引入的所有变化。
This keeps the history of a branch without any of the effects of the branch.
这会保留分支的历史记录,而不会受到分支的任何影响。
(Read: It is not even looked at the changes between those branches. The branches are just merged and nothing is done to the files. If you want to merge in the other branch and every time there is the question "our file version or their version" you can use git merge -X ours
)
(阅读:它甚至没有查看这些分支之间的更改。分支只是合并,对文件没有做任何事情。如果你想在另一个分支中合并,每次有问题“我们的文件版本或他们的版本”,您可以使用git merge -X ours
)
Subtree
子树
Subtree is useful when you want to merge in another project into a subdirectory of your current project. Useful when you have a library you don't want to include as a submodule.
当您想将另一个项目合并到当前项目的子目录中时,子树很有用。当您有一个不想作为子模块包含的库时很有用。
回答by Jakub Nar?bski
Actually the only two strategies you would want to choose are oursif you want to abandon changes brought by branch, but keep the branch in history, and subtreeif you are merging independent project into subdirectory of superproject (like 'git-gui' in 'git' repository).
实际上,如果您想放弃分支带来的更改,而将分支保留在历史记录中,那么您唯一想要选择的两种策略是我们的策略,如果您将独立项目合并到超级项目的子目录中(例如'git-gui'),则选择子树git' 存储库)。
octopusmerge is used automatically when merging more than two branches. resolveis here mainly for historical reasons, and for when you are hit by recursivemerge strategy corner cases.
octopusmerge 在合并两个以上的分支时自动使用。 在这里解决主要是由于历史原因,以及当您遇到递归合并策略的极端情况时。
回答by thaddeusmt
"Resolve" vs "Recursive" merge strategy
“解决”与“递归”合并策略
Recursive is the current default two-head strategy, but after some searching I finally found some info about the "resolve" merge strategy.
递归是当前默认的双头策略,但经过一番搜索,我终于找到了一些有关“解决”合并策略的信息。
Taken from O'Reilly book Version Control with Git(Amazon) (paraphrased):
摘自 O'Reilly 的书籍Version Control with Git( Amazon)(释义):
Originally, "resolve" was the default strategy for Git merges.
In criss-cross merge situations, where there is more than one possible merge basis, the resolve strategy works like this: pick one of the possible merge bases, and hope for the best. This is actually not as bad as it sounds. It often turns out that the users have been working on different parts of the code. In that case, Git detects that it's remerging some changes that are already in place and skips the duplicate changes, avoiding the conflict. Or, if these are slight changes that do cause conflict, at least the conflict should be easy for the developer to handle..
最初,“解决”是 Git 合并的默认策略。
在交叉合并的情况下,其中有多个可能的合并基础,解决策略的工作方式如下:选择可能的合并基础之一,并希望最好。这实际上并不像听起来那么糟糕。事实证明,用户一直在处理代码的不同部分。在这种情况下,Git 检测到它正在重新合并一些已经存在的更改并跳过重复的更改,从而避免冲突。或者,如果这些细微的更改确实会引起冲突,那么至少开发人员应该可以轻松处理冲突。
I have successfully merged trees using "resolve" that failed with the default recursive strategy. I was getting fatal: git write-tree failed to write a tree
errors, and thanks to this blog post(mirror) I tried "-s resolve", which worked. I'm still not exactly sure why... but I think it was because I had duplicate changes in both trees, and resolve "skipped" them properly.
我已经使用“resolve”成功合并了树,但默认递归策略失败了。我遇到了fatal: git write-tree failed to write a tree
错误,多亏了这篇博文(mirror),我尝试了“-s resolve”,它奏效了。我仍然不确定为什么......但我认为这是因为我在两棵树上都有重复的更改,并且正确地解决了“跳过”它们。
回答by Rene B.
As the answers above are not showing all strategy details. For example, some answer is missing the details about the import resolve
option and the recursive
which has many sub options as ours
, theirs
, patience
, renormalize
, etc.
由于上述答案并未显示所有策略详细信息。例如,某些答案缺少有关导入resolve
选项的详细信息,并且recursive
其中包含许多子选项ours
,例如theirs
、patience
、renormalize
、 等。
Therefore, I would recommend to visit the official git
documentation which explains all the possible features features:
因此,我建议访问官方git
文档,其中解释了所有可能的功能特性: