14

我有一个拉取请求,Github 说它不能自动合并。此更改在 master 一些提交之后,但没有冲突。

手动合并我没有任何冲突,我得到这个输出:

(on master)
$git merge otherbranch
[vim pops up for commit message, :wq]
Auto-merging <file>
Merge made by the 'recursive' strategy.
<file> | 1 +
1 file changed, 1 insertion(+)

这就是Github不能自动合并的原因吗?无论如何,它都会从命令行自动合并。这对 Github 来说还不够自动化吗?

4

3 回答 3

13

原因是git merge默认情况下使用称为“递归”合并的策略。它能够执行 3 路合并:从一侧获取补丁,并将该补丁应用到另一侧,以生成新文件。它也递归地执行此操作,在更复杂的情况下,已经发生了很多分支和合并,并且有多个合并基础用于合并的两个提交。

我最近遇到了同样的情况:

$ git merge-base --all 90d64557 05b3dd8f
711d1ad9772e42d64e5ecd592bee95fd63590b86
f303c59666877696feef62844cfbb7960d464fc1
$

使用 2 个合并基础,不可能进行 3 路合并。因此,“递归”策略通过首先递归到这两个提交的合并来解决这个问题:

$ git merge-base 711d1ad9 f303c596
3f5db59435ffa4a453e5e82348f478547440e7eb
$

好的,只有一个合并基地,所以可以开始三路合并。两边有什么变化?

$ git diff --stat 3f5db594 711d1ad9
 normalize/coll.py      | 116 ++++++++++++++++++++++++++++++++++++++-----------
 normalize/visitor.py   |  49 ++++++++++-----------
 tests/test_property.py |  10 +++--
 3 files changed, 120 insertions(+), 55 deletions(-)
$ git diff --stat 3f5db594 f303c596
 normalize/identity.py  | 38 +++++++++++++++++++++++++++++++-------
 tests/test_property.py |  2 ++
 2 files changed, 33 insertions(+), 7 deletions(-)
$ 

这两个差异都对同一个文件进行了更改,因此无法使用仅从每一侧获取每个文件的较新版本(索引合并)的简单策略来解决它们。相反,git 从一侧获取新文件,并尝试将补丁从另一侧应用到它。结果是一个组合提交,可以像这样模拟:

$ git checkout -b tmp
Switched to a new branch 'tmp'
$ git reset --hard f303c59666877696feef62844cfbb7960d464fc1
HEAD is now at f303c59 record_id: throw a more helpful error if record identity is not hashable
$ git merge 711d1ad9772e42d64e5ecd592bee95fd63590b86
Auto-merging tests/test_property.py
Merge made by the 'recursive' strategy.
 normalize/coll.py      | 116 ++++++++++++++++++++++++++++++++++++++-----------
 normalize/visitor.py   |  49 ++++++++++-----------
 tests/test_property.py |  10 +++--
 3 files changed, 120 insertions(+), 55 deletions(-)
$ git diff --stat 3f5db594 HEAD tests/test_property.py
 tests/test_property.py | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
$

然后它返回到原来的 3-way 合并,使用这个合并结果作为它的起点;这也涉及对同一文件的更改:

$ git diff --stat HEAD 90d64557| grep selector
 normalize/selector.py          |  17 +--
 tests/test_selector.py         |  19 ++--
$ git diff --stat HEAD 05b3dd8f| grep selector
 normalize/selector.py  | 29 +++++++++++++++++------------
 tests/test_selector.py |  9 +++++++++
$

然而,再次更改文件的不同部分,因此获取差异并将其应用于另一侧是成功的。

因此,C git 能够通过首先在两个起点的两个合并基础上进行 3 路合并,然后对正在合并的两个原始提交和中间结果进行另一个 3 路合并来解决此合并。第一次合并。

Github 的自动解析并没有做到这一点。它不一定没有能力,而且我不确定它确实实现了多少递归策略,但出于谨慎的考虑,这是错误的,这正是您期望像这样的绿色大按钮所做的事情:-)。

于 2014-04-01T20:33:29.160 回答
5

不,这不是关于合并。这是关于变基的。

你应该尝试在你的本地仓库(克隆你的 fork)中,otherbranchmaster.

首先,确保 master 是原始上游 repo 中最新的一个:

叉子

cd /your/local/repo
git remote add upstream /url/original/repo
git fetch upstream

# Make sure you don't have any local commmit on your master
git branch -f master upstream/master # reset your master branch 
                                     # to the one from upstream repo
git checkout otherbranch
git rebase master

该变基会产生冲突,您应该解决,git add然后git rebase --continue.

最后,只需push --force将您的分支转移到您的 fork:这将自动更新您的拉取请求(无需执行其他操作)。

git push -u -f otherbranch origin

(如果已经推过一次,一个git push就够了)

在此处查看有关拉取请求的更多提示

于 2013-10-17T20:29:36.900 回答
0

默认情况下,在确认合并提交的提交消息之前,Git 不知道它是否可以自动合并您的分支。

如果您知道不会有任何冲突,则可以通过更改GIT_EDITOR为非交互式工具来自动化递归自动合并的过程,例如通过添加cator true

GIT_EDITOR=true git merge otherbranch

对于pull. 您还可以指定合并策略,如-X theirs-X ours

或另一种方法是变基(添加-r到您的pull命令)。

于 2016-07-24T13:51:34.503 回答