首页 > 解决方案 > 在 git 中合并拉取请求会导致上游分支领先于原点

问题描述

术语:

  1. 本地分支称为master
  2. github 上的存储库称为 origin/master
  3. 我分叉的根存储库称为上游/主存储库。

现在假设我的 origin/master 是上游/master 之前的一个提交

所以我为上游/主创建了一个拉取请求,并假设上游存储库的所有者接受了拉取请求并将其合并。

这会在上游存储库中创建一个 +1 提交,并带有消息“从 githubuser/branchname 合并的拉取请求”。所以现在在 github 上它显示“这个分支(origin/master)提前 1 个提交,上游/master 后面有 1 个提交。” 尽管实际上,这些分支中的代码实际上是相同的,而且它们应该是均匀的。

我试图通过去这里解决这个问题:在不推动的情况下清理分支,但它看起来更像是一个 hack。

有没有办法在不向上游做出额外承诺的情况下推入上游。只是合并拉取请求,以便上游/主和源/主分支是均匀的?

标签: gitgithub

解决方案


问题的核心在于 GitHub。(我稍后会详细介绍。)因此,您的问题的答案是no 和 yes

有没有办法在不向上游做出额外承诺的情况下推入上游。只是合并拉取请求,以便上游/主和源/主分支是均匀的?

这里涉及四类人:

  1. 那些对 GitHub 本身进行编程的人。他们控制出现在一个人的网络浏览器中的内容,即您在页面上看到的那个绿色按钮,上面写着“合并此拉取请求”,它的边缘有一个小的下拉箭头,如果单击该箭头,您可以选择三种类型中的一种合并。

    三种类型的合并包括您想要的操作。因此,如果他们将其更改为添加第四种合并,或者更改现有的三种合并中的一种,或者类似的东西,这可以让第 3 组中的每个人都能做你想做的事。

  2. 对上游存储库具有管理访问权限的人员。他们可以git push直接访问上游存储库。这意味着他们可以使用命令行 Git(根本不是 GitHub)来执行您想要的操作,然后运行git push以更新 GitHub 上的存储库。

  3. 那些通过 GitHub 提供的界面对上游存储库具有写访问权限但没有管理访问权限的人。他们不能做你想做的事——至少,直到并且除非第 1 组的人将其添加为选项。

  4. 那些没有写权限的人(大概包括你自己):他们做不到。

现在,至于那些 GitHub clicky 按钮——或者更确切地说,按钮单数,具有三种模式:提供的三种模式是这样标记的:

  • 合并。

    您可能认为这可以完成这项工作,但事实并非如此,因为它运行相当于. 很明显,部分是。这部分比较棘手:它是在. 这是通过单击“比较和拉取请求”点击按钮提交的特定提交的提交 ID。git checkout branch && git merge --no-ff -m message hashbranchmessageMerge pull request #number from repositoryhashrefs/pull/number/head

    如果 GitHub 使用等价的,和, 你会得到你想要的。当然,不会有包含 text 的提交。不过这样就好了。(这是我希望他们添加的新模式。他们可以称之为Merge 而无需额外的提交Fast-forward,也许。)git checkout branch && git merge --ff-only hashbranchhashMerge pull request ...

  • 变基和合并

    这会将当前不在分支上的拉取请求提交(可能不止一个)添加到分支中。它运行相当于(也许与或同样)。最终结果是来自拉取请求的提交被复制,而不是合并到具有新的和不同哈希 ID 的新提交。合并请求在没有添加合并提交的情况下完成,所以没有消息。git checkout branch && git rebase --force-rebase hash--merge--strategy mergeMerged pull request ...

    你可能会认为,如果要复制的一个或多个提交已经在正确的位置——即,在点击按钮之前刚刚超过分支的尖端——GitHub 不会复制提交,而是直接使用它们原样,如果他们运行相当于git rebase without --force-rebase or会发生的情况--no-ff。但这种情况并非如此。我不知道这是否有一些好的(GitHub 内部的)原因。

  • 挤压和合并。

    这相当于. (这里是多余的:暗示。这是命令行 Git 实现的一个不必要的特性,因为如果你真的想要,你可以指定它。)git checkout branch && git merge --no-commit --squash hash && git commit -m message--no-commit--squash--no-commitgit merge --squash --no-commit

    因为这会产生一个新的提交,它不会以任何方式与引入其效果的提交相关联,所以这显然完全不适合实现你想要的。

概括

那些对上游存储库具有写入权限的人可以将您的拉取请求放入他们控制的计算机上的 Git 存储库中,手动合并它,然后将结果推送回 GitHub 上的上游存储库。这就是Tobias K. 在评论中所指的内容。那将实现您想要的。

如果 GitHub 要添加我希望他们添加的合并模式,当前将您的拉取请求与 Web-UI 合并按钮合并的用户将能够一步完成,而无需涉及他们自己的计算机和 Git 命令行命令。但如果没有这种额外的模式,他们就做不到。

他们现在实际使用的是Rebase 和合并模式。正因为如此,我们可以说:

所以现在在 github 上它显示“这个分支(origin/master)提前 1 个提交,上游/master 后面有 1 个提交。

如果他们使用Merge模式,您会看到自己落后了一个提交,但没有提前一个提交。这对你来说会更友好,但在某些方面,对他们自己(可能还有他们存储库的其他用户)不太友好。当他们使用Rebase 和 merge时,他们最终会复制你所有的提交,所以如果你之前有k个提交,你会突然领先k个,落后 k 个:你领先的k 提交,带有你的哈希 ID,并且你后面的k他们提交的副本,以及他们的哈希 ID。

从上游的Rebase 中恢复并合并

请注意,您可以通过在自己的计算机上执行以下操作来恢复:

git fetch upstream
git checkout $branch
git rebase upstream/$branch
git push --force-with-lease origin $branch

(其中$branch代表您的分支名称)。获取他们的fetch提交副本。checkout您为 rebase执行的位置rebase1git push新的提交发送到您的 fork(如果它们不存在),然后请求 GitHub 更改您的 fork 的想法,以指向最后一个此类复制的提交,即使这会丢弃一些提交,也会$branch成功(就像 by ),但是如果被丢弃的提交不完全符合预期,则失败 ( )。--force--force-with-lease


1实际上,您可以一步完成,因为git rebase您可以在开始变基之前检查分支,但我认为这样更清楚。要一步完成,请使用git rebase origin/$branch $branch.


推荐阅读