如何将其他分支的未合并上游拉取请求应用到我的分支中?

547

我在 GitHub 上 fork 了一个项目,但该项目有一个新的 pull request 尚未被作者合并,我希望将其合并到我的 fork 中。

有没有简单的方法将其他 fork 的 pull request 合并到我的 fork 中?还有其他需要注意的地方吗?


8
以下是指示内容链接:https://gist.github.com/piscisaureus/3342247 - Piotr Migdal
2
如果您使用git命令进行操作,这是否会在GitHub的网络图上反映出来? - ADTC
也许找到所有的分支也很有趣:https://stackoverflow.com/q/47798937/10245 - Tim Abell
8个回答

371

更新:通过网页实现

您也可以通过Github网页进行此操作。

我假设您已经拥有一个基于共同仓库(BaseRepo)的分支(MyFork),而该分支中包含您感兴趣的来自另一个分支(OtherFork)的拉取请求。

  1. 导航到您想要将其加入您的分支(MyFork)中的发起拉取请求的分支(OtherFork
  2. 进入OtherFork的拉取请求页面
  3. 单击“新拉取请求”
  4. 应该提供待处理的拉取请求。记得选择相应的OtherFork分支。在左侧作为基础库选择您的分支(MyFork)(重要)。
  5. 现在,查看拉取请求选项应更改为创建拉取请求。单击此选项。

现在,您应该在您的分支(MyFork)中有一个待处理的拉取请求,您可以轻松地接受它。


9
工作得很好。比命令行简单得多,而且容易检查更改。谢谢。 - Alveoli
3
我有困难找到如何进入 UI 上的“OtherFork”。要轻松到达那里,只需通过 GitHub 用户名修改 URL。例如,https://github.com/userName/repoName。 - Charles
4
我无法看到第4步提到的待处理拉取请求。相反,我从右侧的“比较”下拉菜单中选择了与由OtherFork创建的拉取请求对应的分支。然后,我如上所述选择左侧作为基础分支,并成功创建了拉取请求。 - seddonym
2
除非没有分支,否则它可以工作。例如:https://github.com/OculusVR/RakNet/pull/61/files - Milan Babuškov
1
GitHub网站上的确切词语可能已经过时,但是流程是正确的。非常简单 - 谢谢! - kevnk
显示剩余4条评论

296
你可以很容易地手动完成以下操作:
  • 将另一个分支作为您的仓库的远程仓库添加:

    git remote add otherfork git://github.com/request-author/project.git
    
  • 获取他的存储库提交记录

  • git fetch otherfork
    
    你有两种选项来应用这个拉取请求(如果你不想选择选项1):
    1. 如果您不关心也应用了在原始版本和拉取请求之间添加的可能存在的提交,那么您可以将此拉取请求所形成的分支进行变基。

      git rebase master otherfork/pullrequest-branch
      
      如果你只想要拉取请求中的提交记录,那么请识别它们的SHA1值并执行以下操作:
      git cherry-pick <first-SHA1> <second-SHA1> <etc.>
      

182
实际上,你不应该使用 cherry-pick,因为它会创建新的提交记录...这反过来会在将拉取请求发送给上游时造成混乱。相反,你应该像拉取请求所要求的那样进行合并。你也不需要添加一个远程仓库。可以使用 git pull URL branchname 命令。 - Tekkub
3
@Tekkub同意,避免与新创建的提交混淆可能是更好的选择。在我看来,合并不够优雅,因为你可能会将来自你要合并的分支的其他更改也带入其中。 - CharlesB
8
是的,但在这种情况下,他特别询问如何将拉取请求合并到他的分支中。拉取 == 合并。 - Tekkub
1
你至少应该掌握最重要的操作之一:git merge - JonnyJD
5
针对那些和我有一样“心理瑕疵”的人,“otherfork”不是指原始仓库,而是指源自分叉(fork)到原始仓库的拉取请求所引用的提交。忽略原始仓库,直接转到发起拉取请求的分叉(fork)。您需要手动提取与该拉取请求相关的提交,并将其与您自己的合并。 - Michael Khalili
显示剩余5条评论

85

就像 Tekkub 先前所说的那样,您可以直接拉取分支。 大多数情况下,在 GitHub 上,分支只是请求用户的项目分支中的“master”。

例如:git pull https://github.com/USER/PROJECT/ BRANCH

并且作为实际示例:

假设您复制了一个名为 safaribooks 的 github 项目,并且在原始项目中有以下拉取请求,您想将其放入您的分支中:

enter image description here

然后,在您的分支克隆的项目文件夹中运行:

git pull https://github.com/fermionic/safaribooks.git fix-str-decode

23
不足之处在于该分支可能还包含拉取请求以外的其他内容。此外,您还需查找拉取请求作者 fork 的正确 URL。如果您想使用一行命令,则最好使用 git pull https://github.com/{upstream/project} refs/pull/{id}/head - jbyler
4
如果分支中有其他内容,我相信GitHub会更新拉取请求。 - Tim Malone

30

该项目的拉取请求可能来自许多不同的作者(分支),你可能不希望为每个分支创建一个单独的远程分支。此外,您不想对提交拉取请求时作者使用的分支或作者主分支中可能存在的其他内容作出任何假设。因此,最好按照上游存储库中显示的方式引用拉取请求,而不是按照其他分支中显示的方式。

步骤1:

git remote add upstream <url>

你可能已经完成了这一步,但如果没有,请为上游项目定义一个远程。URL 是你 fork 的项目的克隆 URL。更多信息请参阅配置 fork 的远程同步 forkupstream 是你为远程设置的名称,虽然它可以是任何内容,但 upstream 是传统名称。

步骤2:

git pull upstream refs/pull/{id}/head

...其中{id}表示拉取请求编号。 upstream是远程拉取的名称,即如果您完全按照步骤1,只需使用"upstream"。它也可以是一个URL,在这种情况下,您可以跳过步骤1。

步骤3:

为合并提交键入提交消息。您可以保留默认值,但我建议提供一个漂亮的单行总结,包括拉取请求编号、解决的问题以及简短描述:

Merge PR#42, fixing VIM-652, support for mapping arbitrary IDEA actions

还可以查看一个相关答案,其中包含创建带有拉取请求的本地分支的变体。最后一个变体:您可以使用git pull upstream refs/pull/{id}/head将提交获取到本地仓库,然后将其引用为FETCH_HEAD(例如,git log ..FETCH_HEAD查看其中的内容,然后git merge FETCH_HEAD)。 - jbyler
我该如何进行变基操作,以便拉取请求位于主分支的最新状态,并避免合并冲突? - Michael Johnston
2
这是我需要的解决方案,因为拉取请求的作者已经删除了他的仓库。 - jswetzen
是的,这也适用于合并来自不再公开可用的存储库的打开PR。 - James

22

以下是对我有用的更详细信息。

我的fork后的repo的.git/config文件内容如下:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
        ignorecase = true
        precomposeunicode = false
[remote "origin"]
        url = git@github.com:litzinger/angular-carousel.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
        rebase = true
[remote "source"]
        url = git://github.com/revolunet/angular-carousel.git
        fetch = +refs/heads/*:refs/remotes/source/*
        fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

然后运行 "git fetch source",它会列出来所有来自forked repo的pull requests。

 * [new ref]         refs/pull/54/head -> origin/pr/54
 * [new ref]         refs/pull/67/head -> origin/pr/67
 * [new ref]         refs/pull/69/head -> origin/pr/69
 * [new ref]         refs/pull/71/head -> origin/pr/71

若要合并特定的拉取请求,请运行“git merge master origin/pr/67”


1
我编辑了我的 .git/config 文件,并添加了 [remote "source"] 行,但对于我感兴趣的项目,这些指令完美地起作用了。我喜欢这个答案。 - philo vivero
3
可以在https://news.ycombinator.com/item?id=9051220和https://help.github.com/articles/checking-out-pull-requests-locally/找到有关此问题的相关建议,这些提示指向了(非常棒的)GitHub特定的只读远程“refs/pull/”名称空间。 - Philip Durbin
如果您使用Smartgit,只需按照https://www.syntevo.com/doc/display/SG/System+Properties中的说明,在smartgit.properties中添加“smartgit.branch.otherRefs=notes;pull”,即可在日志图表中查看这些拉取请求(以及已关闭的请求)- 您还可以从那里合并它们。 - CAD bloke
顺便提一下,您也可以在命令行上尝试使用 git fetch source +refs/heads/:refs/remotes/upstream/ +refs/pull/*/head:refs/remotes/origin/pr/*。 - lib

9

我会采取以下措施:

git checkout master
git remote add #NAME# #ADDRESS TO REPO#
git fetch #USERNAME#
git checkout -b test_fork
git rebase #NAME#/#BRANCH#

我已将更改合并到名为test_fork的测试分支中,以便任何更改都不会影响我的主分支。

如果更喜欢的话,可以像上面描述的那样使用cherry-pick来选取特定的提交。

祝旅途愉快 :)


2
我有一份方便实用的脚本可以完成这个任务。我通过输入以下命令来运行该脚本:
git prfetch upstream

它会获取来自上游分支的所有拉取请求。

要创建脚本,请创建一个名为~/bin/git-prfetch的文件。

该文件应包含以下内容:

Original Answer翻译成"最初的回答"。

#!/bin/bash

if [ -z "$1" ]; then
    echo "Please supply the name of a remote to get pull requests from."
    exit 1
fi

git fetch $1 +refs/heads/\*:refs/remotes/$1/\* +refs/pull/\*/head:refs/remotes/$1/pr/\*

通过设置确保你的路径包括脚本:

将"Original Answer"翻译成中文是"最初的回答"

export PATH="$HOME/bin:$PATH"

你可以将这个文件添加到~/.bashrc中,以使更改生效。

现在,请确保你添加了你想要从中获取拉取请求的分支:

git remote add upstream https://github.com/user/repo.git

And then

git prfetch upstream

0
简短回答:
前往原始仓库的拉取请求,并查看URL。

enter image description here

URL中的高亮部分是拉取请求的ID。
运行以下命令:
git pull upstream refs/pull/<pull_req_id>/head

能否将PR中的提交压缩成一个单一的提交,就像我们使用“压缩合并”按钮一样? - undefined

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