【问题标题】:Github can't merge branch, no conflicts, manually it auto-mergesGithub 不能合并分支,没有冲突,手动自动合并
【发布时间】:2013-10-26 05:02:32
【问题描述】:

我有一个拉取请求,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 来说还不够自动化吗?

【问题讨论】:

    标签: git github git-merge


    【解决方案1】:

    原因是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(-)
    $
    

    然后返回到原来的三路合并,以此合并结果为起点;这也涉及对同一文件的更改:

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

    【讨论】:

    • 对递归合并策略的很好补充。 +1 很好地补充了我自己的答案。
    【解决方案2】:

    不,这与merging. It is about rebasing 无关。

    您应该尝试在您的本地 repo(克隆 your fork)中重新设置基础,otherbranch 位于 master 之上。

    首先,确保 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
    

    那个 rebase 会产生冲突,你应该解决它,git add,然后是git rebase --continue

    最后,只需 push --force 你的分支到你的 fork:这将自动更新你的拉取请求(没有其他事情可做)。

    git push -u -f otherbranch origin
    

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

    more tips about pull-requests here

    【讨论】:

    • 好的,我认为这是有道理的。谢谢!
    • 我不确定 rebase 是否相关。作者试图合并。智能本地 git 可以自动完成,但 GitHub 似乎将其 git 限制为一些原始的合并策略,因此无法自动解决冲突。
    • @AndreySemakin 据我所知,当它尝试将 PR 分支合并到原始 master 分支时,在 GitHub 端完成的合并没有“限制”。这里的 rebase(在上游/master 之上)确保一旦任何可能的冲突得到解决,GitHub 完成的下一次合并将是一个微不足道的合并。因此,我更喜欢这种方法(我仍然喜欢,6 年后)
    【解决方案3】:

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

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

    GIT_EDITOR=true git merge otherbranch
    

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

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

    【讨论】:

      猜你喜欢
      • 2020-12-20
      • 1970-01-01
      • 2018-03-03
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 2016-05-28
      • 2014-09-13
      • 2020-07-25
      相关资源
      最近更新 更多