我正在使用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
有什么特别之处?
答案 0 :(得分:2)
git pull
只不过是fetch
后跟merge
。
git pull feature-12345 master
更新您的远程分支origin/feature-12345
和origin/master
,然后将这两个分支合并到您当前的HEAD
。
我不确定为什么git pull origin master
让bitbucket显示master的整个历史记录,我的猜测是,它被混合分支混淆为远程分支(origin/master
,而不仅仅是{{} 1}}),或者可能是因为您将两个分支(master
和origin/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 answered,git 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>
,即使可以,它也不应该。如果它不能,它无论如何都会胜出(在这种情况下,标志是不必要的但是无害的)。如果可以的话,它会因为旗帜而失败:你将得到一个真正的合并,而不是快速前进的非合并。