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協作手段!