Pull Request的正确打开方式(如何在GitHub上贡献开源项目)
GitHub的官方幫助如下:
- Fork A Repo:?https://help.github.com/articles/fork-a-repo
- Using?Pull?Requests:?https://help.github.com/articles/using-pull-requests
- Merging a?pull?request:?https://help.github.com/articles/merging-a-pull-request
- Closing a?pull?request:?https://help.github.com/articles/closing-a-pull-request
- Tidying up?Pull?Requests:?https://help.github.com/articles/tidying-up-pull-requests
發現這個官方文檔寫得比較簡單,并沒有提到開源項目協作方式的一些必要的trick(比如建立topic branch),還有PullRequest的運作細節也沒有提到。寫個簡單的總結補充一下。
Step 1: Fork原項目
這個不解釋了,單擊一下鼠標就能做到的事情。參見GitHub幫助的原文。
記得用git remote add添加上游遠程庫的地址,否則無法追蹤上游庫的更新。
Step 2: 創建你的主題(topic)branch
這一步非常重要。GitHub的幫助里沒有提到創建主題branch的必要性,你當然可以直接在原項目的默認branch(如master)上進行工作,但實際上:
如果打算為原項目作貢獻,強烈建議你為每個主題創建一個單獨的branch。
舉例:如果需要修復原項目的一個和Unicode相關的issue:
$ git branch fix-unicode-error $ git checkout fix-unicode-error然后在自己的主題branch(這里是fix-unicode-error)下進行工作。
Step 3: 在主題branch下完成需要的工作
記得push相應的主題branch到GitHub。
*(針對貢獻者)rebase還是merge?
從實用的角度來講,
- 當你在主題branch下工作,想要導入來自上游庫的(與你當前的工作不沖突的情況下)更新時,使用git rebase。
例如,(假設上游branch為upstream/master)
$ git rebase upstream/master fix-unicode-error或者直接(如果當前branch已經是fix-unicode-error):
$ git rebase upstream/master這將把當前branch的開發“base(基礎)”推進到一個新的起點,而不會引入多余的commits。
- 當你在某個branch下工作時,git merge可以用來合并來自其他branch的更新。
如果merge的branch來自遠程庫,一次merge操作會增加一個額外的commit(“Merge branch 'master' of something”)。如果在一個需要發送Pull?Request的主題branch下面進行這種操作,(我個人覺得)這不是一種干凈的手段。
當你在主線branch(例如master)下進行開發時,git merge可以用來吸收其他開發branch引入的新特性(包括主項目維護者用來直接merge?Pull?Requests),很恰當。
Step 4: 發送第一個Pull?Request
GitHub的界面:左邊選擇base branch,右邊選擇head branch。
-
base branch:相當于target branch,你希望Pull?Request被merge到上游項目的哪個branch里。
- 為什么要叫base?branch:base可以理解為你在進行git rebase操作時的那個“base”,也就是你的主題branch所基于的開發base(基礎)。
-
head branch:相當于source branch,你希望自己開發庫里的哪個branch被用來進行Pull?Request(當然也就是你的主題branch)。
- 為什么要叫head?branch:參見下面關于head的定義。
注意head與HEAD(大寫)的區別:
-
head:簡單地理解,就是指向某個commit對象的一個reference。它可以是一個branch的名稱(例如,默認的master),也可以是一個tag的名稱。一個庫可以同時有任意多個head。
-
HEAD:當前活動的head。在任意時刻,存在且僅存在一個HEAD。它可以是指向當前branch的head(比如,指向master,假如master是當前branch的話);也可以不指向任何特定的branch(這叫做detached HEAD)。
系統會從你選擇的head branch(在這里,是主題branch)的這個head開始匹配所有不包含在base branch中的commits,然后自動視作你的主題branch相對于base所增加的新特性,放進同一個Pull?Request中提交。
Step 5:?Pull?Request發送之后……
一旦你從自己的主題branch(例如fix-unicode-error)推送了一條Pull?Request,那么在這條Pull?Request被關閉之前,再次向這個branch里push代碼,所有的commits都會被自動追加到這個Pull?Request后面(不需要再另開Pull?Request)。
這個功能尤其有用,比如你最初提交的Pull?Request里存在某些問題,項目維護者要求你打回去修改;或者要求你給你的新feature添加一條相應的unit test(這種情況簡直太常見了)。只要追加commits到你的這個主題branch中即可。
(題外話:如果原項目有Travis CI,那么它也會在每次追加push之后對Pull?Request重新執行一遍測試)
*(針對項目維護者)cherry-pick、format-patch和am
這幾條命令主要針對項目的維護者,稍微提一下。
git?pull和git merge是GitHub上最常用的merge?Pull?Requests的方式,在命令行下merge之后,GitHub上面的PullRequest也會相應地自動關閉。
如果貢獻者一次提交了多條commits,有些是維護者并不想要的,可以用這幾條命令來選擇性地手動commit。(這也適用于某些項目不是借助于GitHub的Pull?Request,而是通過郵件列表和patch文件來進行協作開發的情形)
在這種情況下,GitHub上面的Pull?Request并不能自動關閉,需要維護者手工操作。
Step 6:?Pull?Request關閉之后
如果是已經被merge后關閉的Pull?Request,你可以在頁面的最下方找到一個“Delete this branch”的藍色按鈕。
這表明這個主題branch的歷史使命已經完成(fix-unicode-error的commit已經被合并到主項目中),可以安全地從遠程庫中刪除了。
在本地庫中亦可刪除這個branch:
$ git branch -d fix-unicode-error反之,如果你的主題branch并沒有被merge就被維護者關掉的話,你還可以繼續再拿它來開新的Pull?Request去騷擾主項目(�0�7▽‘ )。
總結
在哪些情況下可以直接使用master branch來提交Pull?Request:
- 你只想為主項目貢獻某一處代碼,貢獻完自己的repo就可以扔的那種。
- 你打算為主項目長期貢獻代碼,而且希望追隨原項目的主線開發,不保留自己的特性。
- 你打算為主項目長期貢獻代碼,默認master branch追隨原項目主線,把自己的特性放到別的branch中。
在哪種情況下應該使用主題branch來提交Pull?Request:
- 想用master branch完全來做自己的開發。在這種情形下:
- 會從上游庫合并更新,但是這些merge本身的commits顯然不可能作為返還到上游庫的Pull?Request的一部分。
- 存在自己的(未被merge或者不想被merge到上游庫的)commits。
鑒于Git的分布式開發哲學,每一個庫均可以看作是一個獨立的項目,顯然是后一種(為每一個新特性建立一個專門的主題branch來向主項目推送Pull?Request)的貢獻方式更可取。
總結
以上是生活随笔為你收集整理的Pull Request的正确打开方式(如何在GitHub上贡献开源项目)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员相亲记之准博士mm
- 下一篇: 倒数秒跳转页面实现代码。