GitHub中是否支持依赖的拉取请求?

112

目前我正在处理一个非常大的拉取请求。为了使代码审查变得更加可管理,我们的想法是将完整的拉取请求拆分成相互依赖的独立部分。

例如:

  • 拉取请求1:创建接口:接口A和B并重构代码。
  • 拉取请求2:接口A实现和测试(依赖于拉取请求1)。
  • 拉取请求3:接口B实现和测试(依赖于拉取请求2)。
  • 拉取请求4:混合实现的测试(依赖于2+3)。

在GitHub中是否有一种方法可以同时提交这四个拉取请求并反映它们之间的依赖关系?


5
通常我只是提及依赖关系,然后将PR链接在一起,评审人就会知道。添加PR1,添加PR2,使用PR1分支作为基础,并提到“这取决于#1”。以此类推。没有必要同时把它们都放进去。 - Schwern
@Schwern 评审人员会知道,但如果一个PR依赖于另一个PR,自动化测试可能会失败。 - Danny W. Adair
@DannyW.Adair 每个PR的分支都基于其依赖PR的分支。例如,PR2将工作,因为它的基础是PR1。 - Schwern
这是一种做法,但不是 OP 解释的方式。他们为什么会写“基于 2 + 3”来解释 PR4 - 如果你采用那种方法,它也可以基于 PR3。 - Danny W. Adair
2个回答

99
2022年更新:虽然GitHub仍然没有原生支持依赖/堆叠式拉取请求的功能,但现在有一些工具可以更轻松地管理适合GitHub的分支层次结构。我最喜欢的是ghstack,它可以将一堆提交转换为自己的分支,而不会丢失PR历史记录,让GitHub能够理解。然后,您可以使用交互式变基来编辑、重新排序、拆分和删除提交,并相应地更新PR。


据我所知,这是不可能的,在我的观点中,这是GitHub与其他代码审查工具相比的主要缺点之一。当您推送相互依赖的提交时,Gerrit会自动设置相关的代码审查,而在Phabricator中,虽然可能更麻烦,但仍然是可以实现的。

还需要记住的是,人们使用GitHub PRs的方式有多种。正常的开源协作方式是派生一个repo并提交跨repo pull请求,但在其他情况下(例如在组织内),您可能会为在同一存储库中的所有差异提交pull请求。我认为在单个存储库中,获取类似于依赖拉取请求的东西更为合理,因为您可以在该存储库中设置提交/分支结构。

以下是一篇博客文章,介绍了如何获得一些依赖拉取请求的优点,我认为这需要所有提交都在同一个repo中: http://graysonkoonce.com/stacked-pull-requests-keeping-github-diffs-small/

总结如下:

  • 要提交5个依赖拉取请求,请创建一个5层深的分支层次结构,并将每个PR作为基于前一个分支的分支进行提交。
  • 要更新第二个拉取请求(共5个),请推送到第2个分支进行更新,然后进行3次合并操作,以将更改集成到第3、4和5个拉取请求中。
  • 由于GitHub不支持更新PR目标分支,因此您需要一次性提交所有更改。在这个例子中,所有5个代码评审都作为单个提交被提交。现在GitHub支持更新PR的基本分支,因此可以逐个提交PR。

这种方法似乎适用于最好以较小的部分进行审核的大型更改(尽管与像git rebase -i之类的东西相比,维护n级深的分支层次结构很麻烦),但它并不真正允许“代码审查流水线”,您可以在不同阶段的相关差异中具有依赖性,并且可以在审核过早的情况下着陆。

其他一些互联网资源似乎也指出了这种限制:

https://www.quora.com/Is-there-a-good-system-for-adding-multiple-pull-requests-to-GitHub

https://muffinresearch.co.uk/how-do-you-deal-with-dependent-branches-on-github/

我的理解是,使用GitHub PR的人通常会尝试构建他们的工作流程,以不依赖于相关代码审查。一些例子:

  • 不要将更改分解为可以独立审核的增量步骤,而是将其提交为一个整体的代码审查,该审查将全部着陆。GitHub仍允许您将代码审查拆分为多个提交,供评审员查看,但它们无法独立批准/着陆。
  • 尝试结构化您的工作,使您在代码的无关部分进行更改,并将它们放在独立分支上,以便您可以使用cherry-picking或其他方法提交独立的PR。您仍然可以使用应用所有更改的本地分支。
  • 如果你的更改依赖于一个未处理的PR,请等待该PR被接受和合并后再提交新的PR。您可以在某个地方提到您有另一个依赖于该PR的PR,也许这会促使代码审查人员更早地处理它。

  • 2
    另外,还可以参考https://wchargin.github.io/posts/managing-dependent-pull-requests/,了解如何处理依赖的拉取请求。 - larsks
    GitHub 的缺点:当然!有一个单词来形容必须先修复或实现其他方面的问题——“预先工作”。拆分预先工作可以说是正确地进行提交的一部分,而且是普遍情况,不是例外,正如 GitHub(和 GitLab)所认为的那样。 - user2394284
    2
    顺便说一下,这是可能的。假设PR B依赖于PR A,因此在B之前必须合并A。您可以基于A使用的分支完成所有与B相关的工作。现在,当A被合并并删除分支A时,B将指向主分支(而不是A)。在这里:https://github.com/isaacs/github/issues/959#issuecomment-642838613 - Levi Lesches

    0

    由于我在一个有多个依赖项的项目中遇到了类似的用例,所以让我在这里添加一个答案。

    在GitHub中没有简单/本地的方法来实现这一点。你可以在评论中提到PR,并且它们之间会有一些链接,但这只是它们之间的链接,没有真正的依赖关系。

    我选择不使用dependencies-action该操作基于PR的开放评论来保证依赖关系。如果操作成功,PR将可以合并;否则,它将失败并阻止合并。

    为了使用这个工作流程,你只需要在.github/workflows中添加以下yaml文件

    on: [pull_request]
    
    jobs:
      check_dependencies:
        runs-on: ubuntu-latest
        name: Check Dependencies
        steps:
        - uses: gregsdennis/dependencies-action@1.3.0
          env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    

    如果您的PR分布在多个存储库中,您可以在所有存储库中添加工作流程。
    既然您的工作流程已经设置好,您可以明确提及您的依赖关系:
    对于PR1:无需额外评论
    对于PR2:添加:依赖于[PR1](链接到您的PR1) 对于PR3:添加:依赖于[PR2](链接到您的PR2) 对于PR4:添加:
    - 依赖于[PR2](链接到您的PR2) - 依赖于[PR3](链接到您的PR3) 这样,您可以根据PR中的单个评论明确声明依赖关系。这也适用于问题 ;)
    如果您需要逐步指南,您可以访问此博客

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接