当使用git merge将主题分支“B”合并为“A”时,我得到了一些冲突。我知道所有的冲突都可以用B的版本解决。

我知道git合并是我们的。但我想要的是类似git merge -s的东西。

为什么它不存在?如何在与现有git命令冲突合并后实现相同的结果?(git从B中检出所有未合并的文件)

仅仅丢弃分支A中的任何东西(合并提交点到树的B版本)的“解决方案”不是我想要的。


当前回答

为什么它不存在?

虽然我在“git命令使一个分支像另一个分支一样”中提到了如何模拟git合并-s,但请注意,git 2.15(2017年Q4)现在更清晰了:

用于合并的'-X<option>'的文档具有误导性 写的是“-s their”的存在,但事实并非如此。

参见Junio C Hamano (gitster)的commit c25d98b(2017年9月25日)。 (由Junio C Hamano—gitster—在commit 4da3e23,2017年9月28日合并)

合并策略:避免暗示“-s their”的存在 -Xours合并选项的说明有一个插入说明 这告诉读者,它与我们的-s非常不同, 这是正确的,但是后面的- xtheir的描述 不小心说“这是我们的相反”,给了一个错误 这种印象也需要提醒读者,它是非常的 不同于他们的-s,而后者在现实中根本不存在。

xtheir是一个应用于递归策略的策略选项。这意味着递归策略仍然会合并任何它可以合并的东西,并且只会在发生冲突时退回到“他们的”逻辑。

关于他们合并战略的相关性的争论最近在2017年9月的帖子中被重新提起。 它承认旧线程(2008年)

简而言之,前面的讨论可以总结为“我们不想要‘-s their’,因为它鼓励错误的工作流程”。

它提到了别名:

mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -

Yaroslav Halchenko试图再次倡导这一策略,但是Junio C. Hamano补充道:

The reason why ours and theirs are not symmetric is because you are you and not them---the control and ownership of our history and their history is not symmetric. Once you decide that their history is the mainline, you'd rather want to treat your line of development as a side branch and make a merge in that direction, i.e. the first parent of the resulting merge is a commit on their history and the second parent is the last bad one of your history. So you would end up using "checkout their-history && merge -s ours your-history" to keep the first-parenthood sensible. And at that point, use of "-s ours" is no longer a workaround for lack of "-s theirs". It is a proper part of the desired semantics, i.e. from the point of view of the surviving canonical history line, you want to preserve what it did, nullifying what the other line of history did.

正如Mike Beaton所评论的那样,Junio补充道:

Git merge -s ours <their-ref>有效地说“标记提交构成<their-ref>在他们的分支作为提交被永久忽略”; 这很重要,因为如果您随后从分支的后面的状态合并,它们后面的更改将被引入,而不会引入被忽略的更改。

其他回答

类似的选项是——strategy-option(简称-X)选项,它接受他们的选项。例如:

git checkout branchA
git merge -X theirs branchB

但是,它更等于-X而不是-s。关键的区别在于-X执行常规的递归合并,使用所选的一方解决任何冲突,而-s则将合并更改为完全忽略另一方。

在某些情况下,使用-X their而不是假设的-s their的主要问题是删除文件。在这种情况下,只需运行git rm,并输入已删除文件的名称:

git rm {DELETED-FILE-NAME}

在那之后,他们的-X可能会像预期的那样工作。

当然,使用git rm命令执行实际删除操作将首先防止冲突的发生。

这将合并现有的baseBranch中的newBranch

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch

如果你在分支A上,请:

git merge -s recursive -X theirs B

在git版本1.7.8上测试

从现在起,我一直使用Paul Pladijs的答案。我发现,你可以做一个“正常的”合并,发生冲突,所以你这样做

git checkout --theirs <file>

通过使用来自其他分支的修订来解决冲突。如果对每个文件执行此操作,则会得到与预期相同的行为

git merge <branch> -s theirs

无论如何,这种努力比合并策略要多!(这是用git 1.8.0版本测试的)

我觉得你真正想要的是

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

这看起来很笨拙,但应该有用。我唯一不喜欢这个解决方案的是git的历史会令人困惑…但至少历史记录将被完全保存,您不需要为删除的文件做什么特别的事情。