pull request是github/bitbucket给开发人员实现便利合作提供的一个feature。他们提供一个用户友好的web界面在进代码之前来讨论这些变更。
简单说,pull request是一种为了开发人员通知team member他们已经完成了一个feature的机制。一旦他们的feature branch ready了,开发人员就通过他们的github帐号执行一个pull request。这将使得每个相干人知晓这个事件,他们需要review这个feature branch的代码,并且需要决定是否merge到master分支上去。
但是pull request并不仅仅是一种notification,他也是一个专门用于讨论这些即将落地代码的细节的论坛。如果有任何问题或意见,同事们可以在pull request中提comments,甚至直接在这个Pull request中修改要落地的代码。所有这些活动都由pull request来跟踪。
和其他的协作模式相比,这个分享commits的解决方案提供了更完美的工作流。SVN和git都可以通过简单的脚本来实现自动推送通知邮件,蛋儿,当需要讨论这些变更时,开发人员通常仅仅依赖于那个邮件本身来讨论。
Pull request详解
当你发起一个pull request,你正在做的就是:请求另外一个developer(比如项目经理)从你的repo中的一个branch拉取(git pull操作)所有commits到他们自己的repo中。这意味着你在发起pull request时需要提供4样信息:source repo,source branch,destination repo, destination branch.
所有这四类信息默认都由bitbucket来提供。然而,依赖于你的团队的工作流模型,你的团队可能需要指定不同的value。上面的图中演示发起了一个请求merge一个feature branch到official master分支的pull request,但是实际上有很多其他的场景需要发起pull request,这里就不一一表述了。
Pull request是如何工作的?
pull request可以在feature branch workflow,或者git flow workflow,或者forking workflow工作流模型下工作。然而,由于pull request需要至少要么两个不同的分支,要么两个不同的repo才能发起,所以pull request对于centralized workflow并不适用。在上面不同工作流模型中使用pull requests虽然有些不同,但是基本流程是一样的:
- 开发人员在他们local repo的一个feature branch上开发feature
- 开发人员push feature branch到一个bitbucket repo中
- 开发人员通过web页面发起一个pull request
- 团队其他成员review代码,讨论,修改代码
- 项目经理(maintainer)merge feature到official repo并且关闭这个pull request
本文后续将探讨pull request在各种工作流模型中是如何来应用的。
feature branch workflow下的pull request
feature branch workflow使用一个共享的bitbucket repo来管理协作,开发人员在互相隔绝的branch上开发feature。但是,开发人员并不是立即merge他们的feature到master分支上去,开发人员应该启动一个pull request来发起接纳他的代码(落地)前对他的feature代码的讨论。
注意在Feature branch workflow中只有一个public repo,所以pull request的destination和source repo总是相同的。典型地,开发人员往往指定他们的feature branch作为source branch,而master branch座位destination branch.
在收到pull request后,项目经理必须决定要干什么。如果feature确实ready to go, 那么他们可以简单地merge到master分支上去并且关闭这个pull request.但是,如果发现PR中的变更有问题需要解决,他们可以在PR中提供comments反馈。而开发人员随后的follow-up commits则直接在相关的comments中显示出来。
也可以对一个并未完全ready的feature发起一个pull request。比如,开发人员在实现一个需求时遇到了困难,他们就可以通过PR来让其他的同事review和给出建议。
Gitflow workflow下的Pull requests
gitflow工作流和feature branch工作流类似,但是定义了一种严格的分支模型。发起一个Pull request使得开发人员可以非常方便地谈论关于release branch或者maintenance branch的变更。
注意在gitflow workflow下,往往feature branch通常就merge到develop branch, release/hotfix branch则需要同时merge到develop和master分支上去。Pull request则可以被用于严格管理所有这些merge过程。
Forking workflow下的pull request
在forking workflow模型下,一个开发人员将他开发完成的feature到他自己的public repo中,而不是push到official 的shared repo中。在这个动作完成之后,开发人员发起一个pull request以便允许项目经理知道他的工作已经ready了可以review落地。
在这个工作流中,PR的通知功能是非常重要和有用的,因为当另外一个开发人员向bitbucket repo中增加commits时,项目经理无从知晓。
既然每个开发人员都有自己的public repo,那么pull request的source repo将和destination repo是不同的。source repo往往就是开发人员的public repo,而source branch就是source repo中包含了变更的那个branch(实际上是开发人员自己push过去的)。如果开发人员希望将feature代码merge到 official codebase中去,那么destination repo就是official repo,而destination branch就是master
Pull request也可以用于在official project之外实现开发人员之间的协同管理。例如,如果一个开发人员和一个同事一起开发一个feature,他们就可以使用同事的bitbucket repo(而不是official的repo)作为destination来发起一个pull request。他们然后就可以使用相同的feature branch作为source/destination branches。这两个开发人员可以在这个PR中讨论和开发这个feature,待这个feature team完成之后,由team leader来发起真正的PR到official repo master分支。。。这种模型使得pull request在forking workflow中的协作非常高效和弹性。
例子:
下面的例子演示在forking workflow中如何使用pull requests。这种流程对于在小team中协作开发或者对于第三方开发人员需要对一个开源项目做贡献。
在本例中,Mary是一个developer,John是项目经理。他们都有自己的bitbucket repo,John拥有official project repo。
首先,Mary需要fork John's repo(official repo),fork之后,Mary就有了一个server-side project repo的clone repo了。
下一步:Mary需要clone她刚刚从John那里forked过来的project official repo到本地,通过执行下面的命令实现:
git clone https://user@bitbuket.org/user/projectforkedrepo.git
注意:git clone命令会自动地创建一个origin remote connection指向Mary的forked repo.
在Mary开始写任何代码之前,Mary需要创建一个新的feature branch.这个branch就是将来做pull request的时候作为source branch的。
git checkout -b some-feature #edit some code git commit -ma "add first draft some feature"
Mary就这样开始不断地提交commit,如果Mary在后来review历史的时候发现有些混乱,她可以通过interactive rebase来删除或者squash不必要的commits。对于大型项目,梳理一个feature的history对于项目经理(maintainer)来说更加容易看明白pull request到底是要干嘛的
在她的feature完成之后,Mary将本地的feature branch push到她的bitbucket repo中去(注意不是official repo哦),使用以下命令:
git push origin some-branch
这条命令将使得她的变更对于项目经理或者其他collaborators可见了。
在bitbucket有了Mary的feature branch之后,Mary就可以通过她的bitbucket帐号执行创建pull request的操作了,这时bitbucket自动populate前面说的4个value,其中Mary forked repo作为source repo, 并且询问她选择source branch,这里Mary需要选择some-feature这个分支,系统还会询问destination repo(John的repo)以及destination branch.
Mary希望将她的feature merge到official repo的代码库中,所以source branch就是some-feature,而destination branch就是master分支。她也需要提供title 和description以便描述清楚这个pull request是干嘛的。如果除了John,还需要其他人需要approve的话,可以在reviewer字段中添加这些人。
在她创建了这个pull request之后,那么会直接通知到John(通过John的bitbucket feed)或者通过email方式通知。
John作为项目经理,他可以接受直接merge,或者提comments,Mary继续修改代码commit/push到Mary repo的some-feature分支,而这些后续的commits将作为follow-up commit汇聚在pull request下。
记住:pull request并不是git-based collaboration workflow的替代,她是一种更加有效方便的review协作手段!