强制git merge不能正常工作,我认为应该

时间:2017-10-12 17:31:40

标签: git merge git-merge

我的提交树看起来像

---A---B---C   master
    \
     D-----E     dev

我想将E合并到master上,以便领先的主提交看起来像完全像E

---A---B--C--F   master
    \       /
     D-----E     dev

所以F应与E完全相同。

我做的是:

> git checkout master
> git merge -X theirs E

生成的F没有错误消息,但 E和F 之间存在一些差异。它们并不完全相同,就像我需要它们一样。

我知道我可以手动合并并修复差异。但是,1)我确实需要E来完全覆盖C和2)我不能把它搞砸了,所以一些自动的方法比手工操作要好得多。

我做错了什么?我需要做些什么不同的事情?

更新:

> git merge -X theirs dev

也没有帮助。结果相同。

3 个答案:

答案 0 :(得分:2)

首先,请注意:您想要的结果是“邪恶合并”的一个例子,它可能会导致某些问题。如果这是你需要的,那就是你需要的;但请注意,在某些rebase操作(以及其他可能的操作)中,可能会错误地解释其结果与默认值不同的合并(尤其是当默认值不冲突时)。

那说:有一些混乱,因为默认合并策略采用-X参数“我们的”或“他们的”告诉它如何解决冲突;但这并没有改变合并操作从双方采取非冲突的变化。更令人困惑的是, 也是一种名为“我们的”的合并策略,完全忽略了其他分支的变化 - 但没有相应的“他们的”策略。

所以你可以做一些事情。一种选择是

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

(您希望最后一次合并是快进;默认情况下会是这样,但如果您的设置更改了默认设置,则可能需要--ff选项。)

这与将dev合并到master并不完全相同,因为父母会被逆转;但如果这对你没关系,那么这可能是最简单的方法。

另一种选择是手动编辑合并。

git checkout master
git merge --no-commit dev

现在,您需要使工作树和索引看起来像提交E。我想是

git checkout dev -- .
git clean

当然,您可以使用git diff进行验证。

这种方法使父母的顺序保持“合理预期” - 但不要忘记,它仍然是一个邪恶的合并。

答案 1 :(得分:2)

TL; DR:您需要-s theirs不存在

但有几种替代品。请参阅此问题的其他答案,搜索StackOverflow以及" git合并策略他们的",和/或仔细阅读Is there a "theirs" version of "git merge -s ours"? (因为原来的querent实际上正在寻找{ {1}},我在下面介绍过)。或者使用以下相当神奇的sh / bash脚本代码:

-X theirs
将您想要的提交消息放入文件git merge --ff-only $(git commit-tree -p HEAD -p dev dev^{tree} -F /tmp/commitmsg) 之后

请确保这是您想要做的事情,因为它几乎从未如此。

描述

/tmp/commitmsg(扩展参数)-Xours并不意味着使用我们的版本使用他们的版本。他们的意思是 ,当发生冲突 时,请使用我们的更改使用他们的更改

这意味着什么

在您的示例中,theirs的提示是提交master,而C的提示是提交dev。因此,如果当前分支为E,则当前提交master。此时无论您是将名称C或提交dev的哈希ID - 传递给E都无关紧要:两者都选择提交git merge作为提交合并

在任何情况下,提交E都是合并基础,因为同时从AC向后追溯到它们遇到的第一个点,到达提交{{1} }。

因此,E将:

  • diff commit A针对提交git merge:这是当前分支中发生的变化,即A
  • diff commit C反对提交ours:这是 A 中发生的变化。
  • 尝试合并这两个差异。

假设在所有三次提交中,其中一个文件名为E。在提交theirs中,我们找到了一些关于猫的线条和一些关于大象的线条。还有更多的线条(关于土豚,蝙蝠,狗,雀,沙鼠,仓鼠,鬣蜥,长耳鹦鹉等等 - 对于字母表中的每一个字母来说都是如此!)但我们现在会专注于猫和大象。 ..还有Shrews,它们是共享的。

在提交animals.txtA相比,对猫有新的或不同的主张。因此,从CA的差异显示了关于猫(C)的这种变化。 Shrews也有变化:

A

在提交C$ git diff <hash-of-A> <hash-of-C> ... @@ ... @@ blah blah -something about Cats +something different about Cats blah blah @@ ... @@ etc -the Shrew flies through the air, carefree +the Shrew swims the ocean, carefree etc 相比,有关于大象的新的或不同的主张。所以E - 到 - A的差异显示了关于大象的这种变化。对Shrews有一个不同的,冲突的更改 - 我们将省略除此之外的所有内容:

A

当Git进入合并这些更改时,它会从E - 到 - @@ ... @@ etc -the Shrew flies through the air, carefree +the Shrew eats rhinos, though it causes indigestion etc 获取对Cats的更改,并从{{1}更改为大象} -to - A这些更改不会发生冲突,因此组合它们没有问题。但它也会看到关于泼妇谎言的变化,而这些变化冲突并且不能合并。

C选项指示Git选择冲突的一方或另一方

因为这里存在冲突,Git需要帮助解决合并问题。默认情况下,Git只声明&#34;存在冲突&#34;,将两个更改写入工作树,并停止冲突,让您自己清理混乱。 (幕后有很多工作可以帮助你解决冲突,但现在这些都不重要。)

使用其中一个A选项,Git被告知选择我们的,或者选择他们的,然后继续前进。但是此仅影响冲突的更改。 Git仍会照常组合非冲突的更改:在上面的示例中,无论您选择哪个E,Git都会同时进行Cat和Elephant更改,而-X只会选择将Shrew更改为挑

合并策略不同

有一个名为-X的Git合并策略,调用为-X,与-X选项非常不同。这个策略告诉Git不要为了合并基础而烦恼,只是为了保持源代码树免受&#34;我们的&#34;承诺。 Git将完成合并提交,之后根本不做任何工作来产生合适的合并。效果是&#34;杀掉&#34;另一个分支,同时保留其提交;这允许你删除其他分支名称,保留提交,以防你想在某个时候查看它们,同时声明你打算永远不再使用它们(但显然不是很确定:-))。 / p>

如果ours存在,它会做同样的事情,除非它会&#34;杀掉&#34; 当前分支支持新分支。有时你可能想要这个,当它们出现时,如果Git有git merge -s ours可能会很好,但无论出于什么原因,它只有-X ours

替换工作,git merge -s theirs的技巧允许你使用附加到任何现有提交的任意现有源树将任意多次提交绑定在一起 - 因此它涵盖了git merge -s theirs(使用{{1} }}和git merge -s ours。生成的提交对象没有名称,但是git commit-tree提交的直接后代,因此-s ours会将其添加到当前分支。

答案 2 :(得分:1)

-X theirsgit merge选项告诉它在使用默认策略(-s recursive)时如何解决合并冲突。可以合并清洁的更改不受影响。合并的文件将包含在两个分支上运行的更改。

ours strategy可用于创建合并提交,忽略合并分支上的更改。为了使var numbers = { x: 'hi', y: 'dawd', z: 'ohgroe', }; function calc({x = "", y = "", z = ""} = {}) { return x + y + z; } console.log(calc(numbers));看起来与F相同,您必须将E合并到master中,但这不是您要求的。

您的请求的可能解决方案(我没有对其进行测试)可能是这样的:

  • 立即执行合并,但在命令行中添加--no-commit选项;这样,Git准备合并提交,但让你审查(并可能改变)它;
  • (强制)签出worktree文件以匹配dev提交中的repo状态;
  • 将所有内容添加到索引并提交。

命令是:

E