Github无法合并分支,没有冲突,需要手动合并或自动合并。

14

我有一个拉取请求,Github说它无法自动合并。这个更改落后于主分支几个提交,但没有冲突。

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

(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来说不够自动化吗?

3个回答

13

git merge 默认使用一种名为 "递归" 的策略。它可以执行三方合并:从一侧获取补丁,将其应用于另一侧以生成新文件。在更复杂的情况下,例如分支和合并发生较多且两个提交之间存在多个合并基时,它也会以递归方式执行。

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

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

由于有2个合并基础,因此无法进行3方合并。因此,“递归”策略首先递归到这两个提交的合并中来解决此问题:

$ git merge-base 711d1ad9 f303c596
3f5db59435ffa4a453e5e82348f478547440e7eb
$

好的,只有一个合并基础(merge base),所以3方合并可以开始。双方都进行了哪些更改?

$ 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(-)
$

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

$ 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 能够通过首先在两个起始点的两个合并基础上进行三方合并,然后在被合并的两个原始提交和第一个合并的中间结果之间进行另一次三方合并来解决此合并。

Github 的自动解决方案没有这样做。它并不一定无法实现,我不确定它实现了多少递归策略,但它会保守地出错,这正是你期望看到这样的大绿色按钮所做的 :-).


递归合并策略的不错补充。+1 对我的回答很好的补充。 - VonC

5

不,这与合并无关。它是关于变基

你应该尝试在本地克隆的分支中,将otherbranch变基到master上。

首先,请确保从原始上游存储库中获取最新的master分支:

fork

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

最后,只需简单地将你的分支强制推送到你的分叉项目中:这将自动更新你的拉取请求(无需其他操作)。

git push -u -f otherbranch origin

如果已经推送过一次,仅使用 git push 命令即可。

查看 有关拉取请求的更多提示,请点击此处


1
我不确定rebase是否相关。作者尝试只进行合并。智能本地git可以自动完成,但GitHub似乎将其git限制为一些原始的合并策略,因此无法自动解决冲突。 - Andrey Semakin
据我所知,GitHub 在尝试将 PR 分支合并到原始主分支时没有“限制” 。在此处进行的基于上游/主分支的变基确保一旦解决了任何可能的冲突,GitHub 进行的下一个合并将是微不足道的。因此,我更喜欢这种方法(即使是 6 年后)。 - VonC

0
默认情况下,Git 在确认合并提交消息之前不知道是否可以自动合并您的分支。
如果您知道不会有任何冲突,您可以通过将 GIT_EDITOR 更改为非交互式工具(例如添加 cat 或 true)来自动化递归自动合并此过程。
GIT_EDITOR=true git merge otherbranch

对于pull也是一样的。您还可以指定合并策略,例如-X theirs-X ours

另一种方法是使用变基(在您的pull命令中添加-r)。


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