为什么要使用“git merge -s ours”?

27

我了解“ours”合并策略(注意在merge周围的引号)实际上不使用来自其他分支的任何提交。

“ours”策略有时被提到为“保留其他历史记录”。但是它将该历史记录记录为“已应用”。很奇怪。 是否存在我需要此行为的情况?

作为替代,您可以导入其他分支并将其历史记录保留在原位。

请注意,我询问的是“-s ours”策略,而不是“-s recursive”选项的“-X ours”选项(它不同之处在于应用那些不冲突的提交)。


虽然很晚了:在这里看看 here - Christoph
6个回答

15

12

另一个原因是当你有一个分支与你的活动分支非常不同步,且你希望用活动分支更新旧分支,但可能的合并冲突使得使用普通合并难以实现。

例如,我的使用情况是:

你有一个主分支和一个开发分支,由于某种原因,你已经几周没有更新过主分支了,而现在尝试将开发分支合并到主分支中会出现合并冲突。你可能想要做的是用当前开发分支的状态覆盖主分支,以使它们保持同步。

在这种情况下,你可以按照另一位SO用户在此处的另一个SO答案所述的步骤进行操作。但请注意我的警告说明

git checkout dev
git merge -s ours master
git checkout master
git merge dev

简短说明一下:最后,我的主分支已经更新到了我的开发分支的最新版本,但开发分支却显示有4个提交需要推送到远程仓库,这很奇怪。应该不需要推送任何内容,因为我只是想要更新主分支。尽管如此,代码似乎没有问题。需要注意的是,在此之前我从未使用过git merge -s ours命令,所以我对它的用法不是100%确定。

我还发现另一个使用ours选项的答案可能对人们有用:https://stackoverflow.com/a/13307342/339803


8
简而言之:共同祖先

详细说明

每当您执行合并操作时,git 将查找当前分支和要合并的分支的共同祖先。然后,git将把另一个分支共同祖先之后的提交合并到当前分支中。

git merge -s ours 完全忽略来自另一个分支的任何内容。它只是创建一个新的共同祖先。

它更改了将来合并的提交范围

以下链接是来自《Pro Git》书籍“高级合并”章节的一个应用案例

例如,假设您从release分支进行了分支,并对其进行了一些工作,稍后需要将其合并回master分支。与此同时,master上的某个错误修复需要被反向移植到您的release分支中。您可以将错误修复分支合并到release分支中,并在将来将release分支再次合并时,通过将同一分支与您的master分支进行merge -s ours来跳过与错误修复提交相关的提交,即使修复已经存在,则没有冲突。

在此示例中,git merge -s ours被用于跳过release分支合并的错误修复提交。


2
我正在使用这个伪合并来追踪其他分支,包括已经废弃的分支。这个额外的分支实际上只有一个文件(叫做branches-list),其中包含活跃和不活跃分支的文本列表,但在重要的点(大多数分支点和“分支结束”,无论是合并还是废弃)开发分支被合并(用“-s ours”)到这个分支中。
这里是我们项目的最新 屏幕截图

screenshot

因此,最后我从主分支(master)创建了elo-test分支,然后从这个分支又创建了stroke-transform-example分支用于我的问题(以及答案 - 尽管这应该是两个不同的提交)。在每个这样的分支点上,更重要的是,在每个分支结束时,如果它没有合并到其他分支中(当我下次清理时会发生在stroke-transform-example上),我现在将这个分支与元分支branches合并,并使用-s ours选项。
然后我可以稍后删除不再使用的分支,而不会丢失它们的历史记录,因此git branch -a命令的输出始终很小。如果我想回顾一下我当时做的事情,我可以很容易地找到它们。(我认为这不是这个选项的真正用途,但它的效果非常好。)

感谢您详细的回答。在执行“merge -sours”之后,区分这个“伪合并”和“真实合并”需要查看差异,我理解得对吗? - Prestel Nué
顺便说一下,我想偶尔尝试一下这个链接(http://www.fencing-game.de/en/rules)(用纸和笔)! - Prestel Nué
1
是的,你说得对。在我的情况下,我只在“branches”分支上使用这些伪合并,所以很容易看出来。这个游戏使用计算机支持更容易玩,因为你不应该看到对手的隐藏点。随意查看我们的程序,可以免费在线玩 :-) - Paŭlo Ebermann

1
另一个用途是作为替代强制推送的选项,不会对其他人造成非快进式更改。
例如,您想要撤销一个(愚蠢的)提交,但您不想执行“git push -f”,因为那样您将花费接下来的半个小时指导客户从中恢复,并且您需要一个更短的替代方案。
git checkout -b temp remote/origin
git revert HEAD
git push temp:origin
git checkout master
git merge origin/master

所以你只需要这样做。
git merge -s ours origin/master

1
这种方法的一个用途是为另一个合并做准备。
假设您有一些下游更改,想将其与新的上游版本合并,但新的上游版本不是旧的上游版本的git后代(可能是因为旧的上游版本是一个稳定分支,已经与主干分开,也可能是因为上游版本实际上是导入工具的结果)。
你可以这样做:
1. 检出新的上游版本。 2. "伪合并"旧的上游版本。 3. 合并新的下游版本。
这样,您的本地更改将被合并,但git不会尝试合并旧的上游更改,因为它认为它们已经被合并了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接