git Github无法合并分支,无冲突,手动自动合并

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19431244/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 09:13:10  来源:igfitidea点击:

Github can't merge branch, no conflicts, manually it auto-merges

gitgithubgit-merge

提问by jpimentel

I have a pull request that Github says it can't automatically merge. This change is behind master a few commits, but without conflicts.

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

Manually merging I don't get any conflicts, and I get this output:

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

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

Is that why Github can't merge automatically? It merged automatically from the command line anyway. Is this not automatic enough for Github?

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

采纳答案by samv

The reason is that git mergeuses a strategy called "recursive" merging by default. It is able to perform 3-way merging: taking the patch from one side, and applying that patch to the other side, to produce a new file. It also does this recursively, in more complicated situations where a lot of branching and merging has been happening and there are multiple merge basesfor the two commits being merged.

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

I recently encountered this same situation:

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

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

With 2 merge bases, a 3-way merge is not possible. The 'recursive' strategy therefore resolved this by first recursing into a merge of those two commits:

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

$ git merge-base 711d1ad9 f303c596
3f5db59435ffa4a453e5e82348f478547440e7eb
$

OK, only one merge base, so the 3-way merging can begin. what's the changes on either side?

好的,只有一个合并基地,所以可以开始 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(-)
$ 

These two diffs both made changes to the same file, so they can't be resolved using a simple strategy of just taking the newer version of each file from each side (an index merge). Instead, git takes the new file from one side, and tries to apply the patch from the other side to it. The result is a combined commit, which can be simulated like this:

这两个差异都对同一个文件进行了更改,因此无法使用仅从每一侧获取每个文件的较新版本(索引合并)的简单策略来解决它们。相反,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(-)
$

It then returns to the original 3-way merge, using this merge result as its starting point; and this also involves changes to the same file:

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

$ 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 +++++++++
$

However again the changes are to different sections of the file, and so taking the diff and applying it to the other side is successful.

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

So, C git was able to resolve this merge by first doing a 3-way merge on the two merge bases of the two starting points, and then doing another 3-way merge on the two original commits being merged and the intermediate result of the first merge.

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

Github's automatic resolution doesn't do this. It's not necessarily incapable, and I'm not sure how much of the recursive strategy it does implement, but it is erring on the side of caution, which is exactly what you expect a big green button like that to do :-).

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

回答by VonC

No, it isn't about merging. It is about rebasing.

不,这不是关于合并。它是关于基础重建

You should try and rebase, in your local repo (cloned of your fork), otherbranchon top of master.

您应该尝试在本地存储库(从您的 fork克隆)中,otherbranchmaster.

First, make sure master is the most recent one from the original upstream repo:

首先,确保 master 是来自原始上游 repo 的最新版本:

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

That rebase will generate conflicts, which you should resolve, git add, and then git rebase --continue.

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

Finally, simply push --forceyour branch to your fork: that will update your pull request automatically(nothing else to do).

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

git push -u -f otherbranch origin

(if it was already pushed once, a git pushalone should be enough)

(如果它已经被推过一次,一个git push人应该就足够了)

See more tips about pull-requests here.

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

回答by kenorb

By default Git doesn't know if it can auto merge your branch or not before confirming the commit message for the merge commit.

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

If you know you won't have any conflicts, you can automate this process of recursive auto-merging by changing GIT_EDITORto non-interactive tool, for example by adding cator true:

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

GIT_EDITOR=true git merge otherbranch

The same for pull. You can also specify merging strategy like -X theirsor -X ours.

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

or another method is to rebase (adding -rto your pullcommand).

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