显示已在目标分支中的提交的 GitHub 拉取请求

Posted

技术标签:

【中文标题】显示已在目标分支中的提交的 GitHub 拉取请求【英文标题】:GitHub pull request showing commits that are already in target branch 【发布时间】:2013-04-24 17:37:49 【问题描述】:

我正在尝试在 GitHub 上查看非主分支的拉取请求。目标分支在 master 后面,pull request 显示 master 提交,所以我合并 master 并推送到 GitHub,但是刷新后它们的提交和差异仍然出现在 pull request 中。我已经检查了 GitHub 上的分支是否有来自 master 的提交。为什么它们仍然出现在拉取请求中?

我还在本地检查了拉取请求,它只显示未合并的提交。

【问题讨论】:

这会影响合并PR的行为吗? 不,只是 Github 上的差异。 有谁知道自托管的 Gitlab 是否有同样的行为? 我建议我们都联系 GitHub 以表达我们对改变这种行为的兴趣 (support.github.com/contact)。如果他们没有收到我们的来信,那么他们就不会知道这有多重要,而且会永远如此。 【参考方案1】:

这是一个很好的解决方法。在 GitHub 中查看 PR 时使用 Edit 按钮将基本分支更改为 master 以外的其他内容。然后将其切换回master,它现在将正确显示最近提交的更改。

【讨论】:

我很惊讶越来越多的人不承认这个解决方案。我怀疑原始的过时拉取请求会很好,但我不喜欢 GitHub 显示所有过时的文件,所以我使用了它,它既保留了评论,又只显示了即将合并的实际更改.谢谢! 这似乎对我不起作用,它只是添加了我将基本分支更改为其他内容然后返回主分支的信息。 cfr:github.com/europeana/search/pull/30 对于它的价值,我刚才再次检查了这个解决方案,它仍然有效。 Calvin 的问题是目标 repo 正在压缩他的 PR,因此添加到目标 repo 中的提交与他的提交不同。他应该每次都重置他的master 分支,而不是合并他们的上游压缩提交,从而有效地复制所有提交。 我在该 PR 中添加了一条评论,提供了更多详细信息。 谢谢,这对我有用。理想情况下,Github 应该自动执行此操作,或者应该像在 Azure Devops SCM 上那样提供更新选项【参考方案2】:

Pull Request 似乎没有跟踪目标分支的更改(我联系了 GitHub 支持,并在 2014 年 11 月 18 日收到回复,说明这是设计使然)。

但是,您可以通过执行以下操作使其向您显示更新的更改:

http://githuburl/org/repo/compare/targetbranch...currentbranch

根据需要替换 githuburlorgrepotargetbranchcurrentbranch

或者正如 hexsprite 在他的回答中指出的那样,您也可以通过单击 PR 上的 Edit 并暂时将基础更改为不同的分支并再次返回来强制它更新。这会产生警告:

确定要更改基数吗?

一些来自旧基础分支的提交可能会从 时间线,旧的评论 cmets 可能会过时。

并且将在 PR 中 leave two log entries:

【讨论】:

是的,我不久前联系了支持人员并得到了相同的回复。他们没有针对这种情况进行优化。这有点令人沮丧。我们解决它的方法是重新设置基础并强制上推,或者关闭拉力并创建一个新的。 这个答案并不能解决问题,只是让用户看到真正的差异。 问题是“为什么它们仍然出现在拉取请求中?”。它回答了这个问题。 @JSoet 行为没有改变,我只是复制了它。请参阅github.com/amillerchip/merge-test/pull/1。提交 07d3349 “添加更多文本”显示在 PR 中,即使它存在于目标分支中:github.com/amillerchip/merge-test/commits/first_branch 但是使用比较 URL 可以看到正确的差异:github.com/amillerchip/merge-test/compare/… 是否有 dear-github 请求进行更改?【参考方案3】:

总而言之,GitHub 不会在拉取请求中自动变基提交历史记录。最简单的解决方案是:

解决方案 1:变基

假设你想从feature-01合并到master

git fetch origin
git checkout feature-01
git rebase origin/master
git push --force-with-lease

如果您正在使用 fork,那么您可能需要将上面的 origin 替换为 upstream。请参阅 How do I update a GitHub forked repository? 了解有关跟踪原始存储库的远程分支的更多信息。

解决方案 2:创建新的拉取请求

假设您要合并 intro masterfeature-01

git checkout feature-01
git checkout -b feature-01-rebased
git push -u origin feature-01-rebased

现在打开feature-01-rebased 的拉取请求并关闭feature-01 的拉取请求。

【讨论】:

一个 rebase 改变了提交哈希,所以它最终会破坏现有的评论 cmets 吗? @haridsv 可能是的。 执行 push --force 时有什么要注意的吗? @haridsv 这不是我的经验。我经常 rebase 中期审查和 cmets 并没有丢失。虽然我确实丢失了 PR 的变化历史 或者代替 --force 使用 --force-with-lease 因为我认为如果有人在 repo 中更改了您的分支,这将安全地退出。【参考方案4】:

对于遇到此问题并对 GitHub 拉取请求行为感到困惑的任何其他人,根本原因是 PR 是源分支提示与源分支和目标分支的共同祖先的差异。因此,它将显示源分支上直到共同祖先的所有更改,并且不会考虑目标分支上可能发生的任何更改。

更多信息在这里:https://developer.atlassian.com/blog/2015/01/a-better-pull-request/

基于共同祖先的差异似乎很危险。我希望 GitHub 可以选择制作更标准的基于 3 路合并的 PR。

【讨论】:

你提到的原因似乎是正确的,但我很困惑,因为通常每当主更新时,我都会将更改合并到我的分支... git checkout my-branch -> git合并主人。拉取请求会立即刷新。共同祖先也会更新吗? 这种行为似乎发生在做rebase而不是merge时 @G.One,真的迟到了回复,但是是的——如果你从那个主分支合并到你的源分支,你就定义了更新了共同祖先。这是您合并的 master 上的提交。【参考方案5】:

当您压缩从目标分支合并的提交时,GitHub 会发生这种情况。

我一直使用 squash 并与 Github 合并作为默认合并策略,包括来自目标分支的合并。这引入了一个新的提交,而 GitHub 不承认这个压缩的提交与 master 中已经存在的提交相同(但具有不同的哈希值)。 Git 可以正确处理它,但您会在 GitHub 中再次看到所有更改,这使得查看起来很烦人。解决方案是定期合并这些拉入的上游提交,而不是压缩和合并。当您想将另一个分支作为依赖项合并到您的分支中时,git merge --squash 并在其他分支实际上已成为 master 后从 master 拉出之前还原该单个提交。

编辑:另一种解决方案是变基并强制推送。干净但改写的历史

【讨论】:

谢谢@achille,这确实是我这边的问题。禁用壁球合并后,它就解决了。 Github Rebase Merge 也会导致这个问题【参考方案6】:

您需要将以下内容添加到您的 ~/.gitconfig 文件中:

[rebase]
    autosquash = true

这将自动实现与this answer 显示的相同。

我是从 here 那里得到的。

【讨论】:

@RonaldRey git rebase 不是一个通用的解决方案,因为它涉及编辑历史。如果每个人都在开发其他人永远不会克隆的私有分支,那很好,但是一旦有人克隆了您的存储库,然后您编辑了历史记录,您最终会得到不同的历史记录。【参考方案7】:

解决此问题的一种方法是在该 PR 中发送 git rebase targetbranch。然后git push --force targetbranch,然后 Github 将显示正确的提交和差异。如果您不知道自己在做什么,请注意这一点。也许先签出一个测试分支来做 rebase 然后git diff targetbranch 以确保它仍然是你想要的。

【讨论】:

或者代替 --force 使用 --force-with-lease 因为我认为如果有人在 repo 中更改了您的分支,这将安全地退出。【参考方案8】:

用两点网址代替三点网址进行比较

而不是

http://githuburl/org/repo/compare/targetbranch...currentbranch

使用

http://githuburl/org/repo/compare/targetbranch..currentbranch

【讨论】:

【参考方案9】:

我尝试了什么以及为什么会这样?

没有一个解决方案对我有用。当我使用two dots 即.. 而不是... 时,GH 上的差异更接近于我所做的更改。但仍然不是我所有的变化。

发生这种情况是因为 GitHub 显示 squash 合并 的方式发生了变化。最佳解释here

它基本上会发生在:

    推送featureBranch的更改 Squash 合并main 当我还在featureBranch 上时,我在本地将它与main 合并。进行更多更改并再次推动它。 但是在 GitHub 上,我看到的变化比我预期的要多。

值得注意的是,这不是 git 问题。相反,这是一个 GitHub 问题。 GitHub 无法判断压缩提交与非压缩提交的总和相同,并导致额外的差异。


解决方案

在您的本地 main 上,撤消并存储所有尚未与 main 合并的更改。为此,我做到了。例如,如果我的 PR 中没有 4 个提交被壁球合并,那么我会这样做:

git reset HEAD~4 git stash save "last 4 commits"

然后使用您刚刚隐藏的内容创建一个新分支。步骤:

git checkout main git checkout -b newBranch git stash apply git add --all git commit -m "some message" git push

【讨论】:

【参考方案10】:

我不太确定这背后的理论。但我多次遇到此问题,并且能够通过执行以下操作来解决此问题。

git pull --rebase

这将从您的原始 repo master 分支中获取并合并更改(如果您有这一点)

然后您将更改强制推送到您的 github 克隆存储库(目标)

git push -f origin master

这将确保您的 github 克隆和您的父 repo 处于相同的 github 提交级别,并且您不会在分支之间看到任何不必要的更改。

【讨论】:

【参考方案11】:

我找到了一种获得正确行为的方法(在 2020 年 11 月进行了测试)。

git merge之后和解决冲突需要使用git merge --continue而不是git commit ...

【讨论】:

【参考方案12】:

一旦我在开始新更改或创建 PR 之前开始执行以下操作,问题就不会发生。

git pull --rebase origin <target-branch>

这基本上确保了从本地添加的任何新更改都堆叠在远程分支中当前的更改之上。因此,我们的本地分支始终位于当前远程头的顶部,并且 PR 中只有新提交。

【讨论】:

【参考方案13】:

如果您太担心搞砸了,请采取安全措施: 转到文件并手动删除更改,然后使用上次提交压缩

git add .  && git commit -a --allow-empty-message -m '' && git reset --soft HEAD~2 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@1)"

我没有冲突,你可以走了!

【讨论】:

以上是关于显示已在目标分支中的提交的 GitHub 拉取请求的主要内容,如果未能解决你的问题,请参考以下文章

Github 拉取请求显示太多更改/提交

多分支管道作业未显示打开的拉取请求

如何使用“合并前需要拉取请求审查”来保护分支

在拉取请求时重命名分支

如何创建从一个分支的 Bitbucket 到 GitHub 中的主分支的合并拉取请求

恢复了来自 github 的拉取请求,但两个分支没有区别