问题的核心在于GitHub内部。(稍后我将详细解释。)因此,对于你的问题,《指环王》项目中的
答案既是“否”又是“是”:
有没有办法推入上游而不向上游进行额外提交。只合并拉取请求,使上游主和原点主分支平等?
这里涉及到四组人:
编写GitHub本身的人。他们控制着出现在您网页浏览器中的内容,即您在页面上看到的那个绿色按钮,“Merge this pull request”(合并该拉取请求),该按钮边缘有一个小下拉箭头,如果单击,则可以选择三种类型的合并。
这三种类型的合并不包括您想要执行的操作。因此,如果他们更改此以添加第四种合并类型,或更改其中一种现有的合并类型,或采取类似的措施,那么就可以让第3组中的每个人都能够做到您想要的事情。
具有上游存储库管理访问权限的人。他们可以直接git push
到上游存储库。这意味着他们可以使用命令行Git(根本不涉及GitHub)执行您想要的操作,然后运行git push
来更新GitHub上的存储库。
通过GitHub提供的接口具有写访问权限,但没有管理访问权限的人。他们无法做到你想要的事情,至少在第1组的人将其添加为选项之前是这样。
没有写访问权限的人(包括您自己):他们无法做到这一点。
现在,就那些GitHub的点击按钮而言——或者说,三种模式的按钮:提供的三种模式标记如下:
合并。
你可能认为这可以完成任务,但实际上并不是这样,因为它运行的等效命令是git checkout branch && git merge --no-ff -m message hash
。其中,branch
很明显,message
部分是Merge pull request #number from repository
。而hash
部分则更加复杂:它是在refs/pull/number/head
下找到的哈希值。这是你提交的特定提交的提交ID,通过你点击“比较和拉请求”的按钮提交的。
如果GitHub使用等效的命令git checkout branch && git merge --ff-only hash
,与相同的branch
和hash
,你将获得你想要的内容。当然,就不会有包含文本Merge pull request ...
的提交了。但这没事。(这是我希望他们添加的新模式。他们可以称之为无额外提交的合并或快进,也许。)
变基合并。
这将添加不在分支上的拉取请求提交(可能有多个)到该分支。它运行的等效命令是git checkout branch && git rebase --force-rebase hash
(也许还带有--merge
或--strategy merge
)。最终结果是,从拉请求中复制的提交被复制到新的提交中,具有新的和不同的哈希ID。合并请求完成后,不会添加合并提交,因此没有Merged pull request ...
消息。
你可能会认为,在要复制的提交或提交已经在正确的位置的情况下,即在点击按钮之前的分支尖端刚刚过去的情况下,GitHub不会复制提交,而是像在没有--force-rebase
或--no-ff
的情况下运行git rebase
一样使用它们。但事实并非如此。我不知道是否有某些好的(GitHub内部)原因。
压缩合并。
这相当于执行git checkout branch && git merge --no-commit --squash hash && git commit -m message
。(这里的--no-commit
是多余的:--squash
意味着--no-commit
。这是git merge --squash
命令行Git实现的一个不必要的特殊功能,因为如果你真的希望使用--no-commit
,你可以直接指定它。)
由于这将创建一个与引入效果的提交没有任何关联的新提交,因此此方法显然完全不适合实现您想要的内容。
摘要
那些有权写入上游存储库的人可以将您的拉取请求合并到他们控制的计算机上的Git存储库中,并手动合并结果,然后将其推回GitHub上游存储库。这就是Tobias K.在评论中提到的内容。这样就可以实现您想要的目标。
如果GitHub添加了我希望它添加的合并模式,当前使用Web UI合并按钮合并您的拉取请求的用户将能够一步完成,而不需要涉及自己的计算机和Git命令行命令。但是如果没有额外的模式,他们就不能这样做。
他们现在实际使用的是变基合并模式。我们可以看到这一点:
所以现在在github上显示“此分支(origin/master)领先于上游/主分支1个提交,落后于上游/主分支1个提交。”
如果他们使用合并模式,您会看到自己落后一个提交,但不会领先一个提交。这对您来说更友好,但在某些方面,对他们(以及其它使用他们存储库的用户)来说不太好。当他们使用变基合并时,他们最终会复制您的所有提交,因此如果您之前领先了k次提交,那么您将突然领先k次并且落后k次:您领先的k次是您的提交,带有您的哈希ID,而您落后的k次是他们的副本您的提交,带有他们的哈希ID。
从上游的变基合并中恢复
请注意,您可以通过在自己的计算机上执行以下操作来从中恢复:
git fetch upstream
git checkout $branch
git rebase upstream/$branch
git push --force-with-lease origin $branch
(这里的$branch
代表你的分支名称)。 fetch
获取它们自己的提交副本。 checkout
将您定位到rebase,而rebase
执行rebase操作。1 git push
将新提交发送到您的fork(如果它们还没有在那里),然后请求GitHub更改您的fork对于$branch
指向最后一个已复制的提交,即使这会删除某些提交(就像使用--force
一样)也会成功,但如果要删除的提交不完全符合预期,则会失败(使用--force-with-lease
)。
1实际上,您可以在一步中完成此操作,因为git rebase
允许您在开始rebase之前检出分支,但我认为以这种方式更清晰。 要在一步中完成操作,请使用git rebase origin/$branch $branch
。
git merge --ff-only featurebranch
在本地合并,然后再进行推送(push)。这只有在master
分支没有与你的特性分支发生分歧时才有效。 - Tobias K.no-ff
),所以你无法在GitHub上干净地完成它,需要从其他地方推送分支。 - Tobias K.