为什么" git pull origin feature-12345 master"更新我的拉取请求分支的唯一方法是?

时间:2017-11-14 06:32:13

标签: git merge version-control

我正在使用BitBucket上的拉取请求,该请求已经打开很长时间(几周,而主人继续快速进展),而且我并不是唯一一个提交提交的人到公关。我还需要让PR与master保持同步。因为有多个人在分支上工作(并且因为它感觉很脏),所以做一个rebase然后git push --force不是一个很好的选择。

在这种情况下,我发现的唯一可行的是以下内容:

git checkout master
git pull origin master
git checkout -b feature-12345 origin/feature-12345
git pull origin feature-12345 master
git push origin feature-12345

上面的关键行是git pull origin feature-12345 master,这会导致提交消息:

Merge branches 'feature-12345' and 'master' of ssh://mybitbucketserver/ABC/xyz into feature-12345

完成此操作后,BitBucket显示了一个很好的"合并"提交"提交" PR的列表,而不是使用来自master的最近提交来提交提交历史记录。

我很高兴我已经知道如何做到这一点,但我的问题是:为什么我需要使用该特定命令,以便以这种方式合并?如果我尝试(在feature-12345分支上):

git pull origin master

然后推,它淹没了我的提交历史。

如果我这样做(我认为它将100%等同于git pull origin feature-12345 master的合并部分,但似乎没有):

git merge feature-12345 master

git pull origin feature-12345 master有什么特别之处?

2 个答案:

答案 0 :(得分:2)

git pull只不过是fetch后跟merge

git pull feature-12345 master更新您的远程分支origin/feature-12345origin/master,然后将这两个分支合并到您当前的HEAD

我不确定为什么git pull origin master让bitbucket显示master的整个历史记录,我的猜测是,它被混合分支混淆为远程分支(origin/master,而不仅仅是{{} 1}}),或者可能是因为您将两个分支(masterorigin/master)合并为第三个分支(origin/feature-12345

让我建议先让你的主人更新,然后在本地合并到你的分支,然后推送最终的分支:

feature-12345

答案 1 :(得分:2)

TL; DR:你想要的是:

git fetch origin

可选地后跟:

git checkout master
git merge origin/master   # *do* allow fast-forward here

接下来是:

git checkout feature-12345
git merge origin/feature-12345   # or git rebase origin/feature-12345

如果需要/需要,接着是:

git merge --no-ff origin/master  # or git merge --no-ff master

作为ElpieKay points out in a comment,您可能想要重新考虑将从主的提示提交到功能分支的策略。它实际上不是错误,但随后将功能分支合并回主分支可能会导致交叉合并,Git会处理,但会产生意外。

描述(长)

作为Gauthier answeredgit pull首先只运行git fetch,然后 - 一旦成功 - git merge(或者有时候不同的Git命令,如果你告诉它)。

棘手的部分是 git pull如何运行git merge。它最初并不像大多数人所期望的那样。

Git' merge动词合并提交git merge的参数指定哪些提交要用作"他们的"提交(S)。您的提交,正常三向合并中的--ours提交,总是 HEAD:当您第一次运行命令时,提交是当前的。 git pull运行{G}命令的方式,当git pull运行git pull时,当您运行git merge时当前的提交仍然是最新的。

普通三向合并的合并基础很简单; git merge-base会为您计算。但是你并没有做一个普通的三方合并。相反,你正在做Git所谓的章鱼合并。为了找到此操作的合并基础,Git使用git merge-base --octopus,为其提供HEAD提交的哈希ID以及您要求合并的每个目标提交的哈希ID。然后,Git将此合并基础与每个要合并的提交进行比较,并结合所有更改。

当你跑步时:

git pull origin feature-12345 master

你告诉你的Git连接到origin上的第二个Git,并要求 feature-12345 {{1 } {,master运行:

git pull

这些名称解析为两个提交哈希ID(可能是不同的哈希ID,但可能只有一个)。如果你的Git还没有这些提交,你的Git现在就会下载这些提交。如果你的Git已经有这些提交,你的Git不需要在这里做任何事情。

下一步取决于您的Git版本。如果您的Git是1.8.4或更新,您的Git"机会性地更新"现在是您的git fetch origin feature-12345 master origin/feature-12345。否则,它会保持不变。

最后,您的origin/master会将这些原始提交哈希ID转储到文件git fetch中。 .git/FETCH_HEAD步骤现已完成。

git fetch代码现在转到第二个Git命令:它运行pull,其中两个哈希ID从git merge <hash-id-1> <hash-id-2>文件中提取。 (它提供了一些额外的参数,如.git/FETCH_HEAD来设置默认提交消息,但这些在这里不太重要。)这就是调用章鱼合并策略。

再次注意,Git正在通过提交哈希ID 进行此合并,而非名称!这是人们在重现效果时遇到这么多麻烦的一个原因:那些哈希ID 可能,特别是如果你的Git很老(1.8.4之前),根本没有任何名字!

如果您只是运行-m,您的Git将从git fetch origin所有分支加载,设置 all 您自己的{ {1}}远程跟踪名称与origin上的提交相对应。然后,您可以运行origin/*以获得相同的章鱼合并。

实际上想要章鱼合并是非常罕见的。但是使用章鱼合并策略会产生副作用:它会阻止Git执行快进操作。当你跑:

origin

Git将检查您当前的提交是否是指定提交的祖先。如果是这样,Git 可以执行合并的快进而不是。如果你没有告诉Git 这样做,这样做,因为它可以。

如果你想要一个真正的合并 - 要避免,正如你所说,&#34;充斥着提交历史记录&#34; - 你可以简单地告诉Git:不要这样做。 git merge origin/feature-12345 origin/master标记(注意双短划线)告诉git merge <single-commit-specifier> ,即使可以,它也不应该。如果它不能,它无论如何都会胜出(在这种情况下,标志是不必要的但是无害的)。如果可以的话,它会因为旗帜而失败:你将得到一个真正的合并,而不是快速前进的非合并。