13 KiB
创建Pull Request
BY 童仲毅(geeeeeeeeek@github)
这是一篇在原文(BY atlassian)基础上演绎的译文。除非另行注明,页面上所有内容采用知识共享-署名(CC BY 2.5 AU)协议共享。
原文以Bitbucket为例,考虑到git-recipes主要面向Github用户,因此栗子替换成了Github。Pull Request在GitLab等平台上也有,用法和本教程基本一致。
Pull request是开发者使用Github进行协作的利器。这个功能为用户提供了友好的页面,让提议的更改在并入官方项目之前,可以得到充分的讨论。
最简单地来说,pull request是一种机制,让开发者告诉项目成员一个功能已经完成。一旦feature分支开发完毕,开发者使用Github账号提交一个pull request。它告诉所有参与者,他们需要审查代码,并将代码并入master分支。
但是,pull request不只是一个通知,还是一个专注于某个提议功能的讨论版。 如果更改导致了任何问题,团队成员可以在pull request下发布反馈,甚至推送后续提交来修改这个pull request。所有的活动都在这个pull request里之间追踪。
和其他协作模型相比,这种共享提交的解决方案形成了更加线性的工作流。SVN和Git都能通过一个简单的脚本发送通知邮件;但是,如果要讨论更改,开发者不得不在邮件里回复。这会变得愈发杂乱无章,尤其是后续提交出现时。Pull request将所有这些功能放入了一个友好的网页,在每个Github仓库上方都能找到。
剖析一个Pull Request
当你提交一个pull request的时候,你做的事情是 请求 (request) 另一个开发者(比如项目维护者)来 拉取 (pull) 你仓库中的一个分支到他们的仓库。也就是说你需要提供4个信息来完成一个pull request:源仓库、源分支、目标仓库、目标分支。
Github会机智地帮你将一些值设为默认值。但是,取决于你的协作工作流,你的团队可能需要设置不同的值。上图显示了一个请求从feature分支合并到官方master分支的一个pull request,但除此之外还有好多种使用pull request的方式。
Pull Request是如何工作的
Pull request可以和feature分支工作流、Gitflow工作流或者Fork工作流一起使用。但pull request需要两个不同的分支或是两个不同的仓库,因此它们不能和中心化的工作流一起使用。在不同的工作流中使用pull request有些不同,但大致的流程如下:
- 开发者在他们的本地仓库中为某个功能创建一个专门的分支。
- 开发者将分支推送到公共的Github仓库。
- 开发者用Github发起一个pull request。
- 其余的团队成员审查代码,讨论并且做出修改。
- 项目维护者将这个功能并入官方的仓库,然后关闭这个pull request。
下面的章节讨论pull request在不同的协作工作流中有哪些不同。
Feature分支工作流中的Pull Request
Feature分支工作流使用共享的Github仓库来管理协作,开发者在单独的feature分支中添加功能。开发者在将代码并入主代码库之前,应该发起一个pull request来启动这个功能的讨论,而不是直接将它们合并到master。
在Feature分支工作流中只有一个公共的仓库,因此pull request的目标和源仓库永远是同一个。一般来说,开发者会将他们的feature分支作为源分支,master作为目标分支。
在收到pull request之后,项目维护者将会做出决定。如果这个功能可以立即发布,他们只需要将代码合并进master,然后关闭pull request即可。但是,如果提议的更改有一些问题,他们可以在pull request下发布反馈。后续提交将会显示在相关评论的下方。
你也可以发布一个未完成功能的pull request。例如,如果开发者在实现一个特殊的需求时遇到了问题,同样可以发布一个包含工作进展的pull request。其他开发者可以在这个pull request后面提供建议,甚至自己发布后续的提交来解决这个问题。
Gitflow工作流中的Pull Request
Gitflow工作流和Feature分支工作流类似,但定义了围绕项目发布的一个严格的分支模型。在Gitflow工作流之上添加pull request使得开发者方便地讨论发布分支或是所在的维护分支。
在Gitflow工作流中的Pull request和上一节中的完全一致:开发者只需在功能、发布或是快速修复分支需要审查时发布一个pull request,Github会通知到其余的团队成员。
功能一般都会合并到develop分支,而发布和快速修复分支会被同时合并到develop和master当中。 Pull request可以用来妥善管理这些合并。
Fork工作流中的Pull Request
在Fork工作流中,开发者将一个完成的功能推送到 他们自己的 仓库,而不是公共的仓库。在这之后,他们发布一个pull request,告诉项目维护者代码需要审查了。
在这个工作流中,pull request的通知作用显得非常有用,因为项目维护者无法获知其他开发者什么时候向他们自己的Github仓库中添加了提交。
因为每个开发者都有他们自己的公共仓库,pull request的源仓库和目标仓库不是同一个。源仓库是开发者的公开仓库,源分支是包含提议更改的那一个。如果开发者想要将功能合并到主代码库,目标仓库便是官方的项目仓库,目标分支为master。
Pull request还可以用来和官方项目之外的开发者进行协作。比如说,一个开发者正在和同事一起开发一个功能,他们可以向 同事的 Github仓库发起一个pull request,而不是官方仓库。他们将feature分支同时作为源分支和目标分支。
两个开发者可以在pull request中讨论和开发分支。当功能完成时,其中一位可以发起另一个pull request,请求将功能合并到官方的master分支中去。这种灵活性使得pull request成为了Fork工作流中尤为强大的协作工具。
栗子
下面的🌰演示了如何将pull request用在Fork工作流中。小团队中的开发和向一个开源项目贡献代码都可以这样做。
在这个栗子中,Mary是一位开发者,John是项目的维护者。他们都有自己公开的Github仓库,John的仓库之一便是下面的官方项目。
Mary fork了官方项目
为了参与这个项目,Mary首先要做的是fork John的Github仓库。她需要注册登录Github,找到John的仓库,点击Fork按钮。
下图显示的是geeeeeeeeek的WeChatLuckyMoney仓库。
选好fork的目标位置之后,她在服务端就有了一个项目的副本。
Mary克隆了她的Github仓库
接下来,Mary需要将她刚刚fork的Github仓库克隆下来。她在本地会有一份项目的副本。她需要运行下面这个命令:
git clone https://github.com/user/repo.git
请记住,git clone自动创建了一个名为origin的远端连接,指向Mary fork的仓库。
Mary开发了一个新功能
在她写任何代码之前,Mary需要为这个功能创建一个新的分支。这个分支将是她随后发起pull request时要用到的源分支。
git checkout -b some-feature
# 编辑一些代码
git commit -a -m "新功能的一些草稿"
为了完成这个新功能,Mary想创建多少个提交都可以。如果feature分支的历史有些乱,她可以使用交互式的rebase来移除或者拼接不必要的提交。对于大项目来说,清理feature的项目历史使得项目维护者更容易看清楚pull request的所处的进展。
Mary将feature分支推送到了她的Github仓库
在功能完成后,Mary使用简单的git push将feature分支推送到了她自己的Github仓库上(不是官方的仓库):
git push origin some-branch
这样她的更改就可以被项目维护者看到了(或者任何有权限的协作者)。
Mary创建了一个pull request
Github上已经有了她的feature分支之后,Mary可以找到被她fork的仓库,点击项目简介下的 New Pull request 按钮,用她的Github账号创建一个pull request。Mary的仓库会被默认设置为源仓库(head fork),询问她指定源分支(compare)、目标仓库(base fork)和目标分支(base)。
Mary想要将她的功能并入主代码库,所以源分支就是她的feature分支,目标仓库就是John的公开仓库,目标分支为master。她还需要提供一个pull request的标题和简介。
下图展示的是将0492wzl/WeChatLuckyMoney(源仓库)的stable(源分支)合并到geeeeeeeeek/WeChatLuckyMoney(目标仓库)的stable(目标分支)。
在她创建了pull request之后,Github会给John发送一条通知。
John审查了这个pull request
John可以在他自己的Github仓库下的 Pull Request 选项卡中看到所有的pull request。点击Mary的pull request会显示这个pull request的简介、feature分支的提交历史,以及包含的更改。
如果他认为feature分支已经可以合并了,他只需点击Merge Pull Request按钮来通过这个pull request,将Mary的feature分支并入他的master分支。
但是,在这里栗子中,假设John发现了Mary代码中的一个小bug,需要她在合并前修复。他可以评论整个pull request,也可以评论feature分支中某个特定的提交。
Mary添加了一个后续提交
如果Mary对这个反馈感到困惑,她可以在pull request后回复,把这里当做是她的功能的讨论版。
为了修复错误,Mary在她的feature分支后面添加了另一个提交,并将它推送到了她的Github仓库,就像她之前做的一样。这个提交被自动添加到原来的pull request后面,John可以在他的评论下方再次审查这些修改。
John接受了pull request
最后,John接受了这些修改,将feature分支并入了master分支,关闭了这个pull request。功能现在已经整合到了项目中,其他在master分支上工作的开发者可以使用标准的git pull命令将这些修改拉取到自己的本地仓库。
如果你希望实践一下,可以按照上面的流程向这个项目发起一个pull request,修改任何你发现的错误😄
接下来怎么做?
你现在应该已经掌握了如何将你的pull request整合到你的工作流。记住,pull request不是替代任何Git工作流的万金油,而是一种让队员间协作锦上添花的工具。
这篇文章是『git-recipes』的一部分,点击目录查看所有章节。
如果你觉得文章对你有帮助,欢迎点击右上角的Star🌟或Fork🍴。
如果你发现了错误,或是想要加入协作,请参阅Wiki协作说明。




