【转】GitHub 从单机到联机:玩转 Pull Request
最近在參與一個叫 Exercism 的項目,這是一個由 GitHub 生態工程師 Katrina Owen 發起的編程練習社區,提供了超過50門語言的練習。作為用戶,你僅需使用命令行工具即可下載和提交練習,提交后還可以和社區中其他學習者交流討論。
Exercism的社區互動性
在和世界各地的小伙伴們愉快地玩耍了十來天之后,我覺得可以為這個社區貢獻些什么。由于我比較擅長 Python,所以決定為 exercism/python 這個倉庫貢獻代碼。我知道很多朋友都是在“單機模式”下使用 GitHub ——一個人默默地維護自己的倉庫,卻始終沒有和他人互動乃至協作過。接下來我將分享第一次踏入開源世界、“聯機”使用 GitHub 的體驗,并將對應 GitHub Flow 手把手教會你怎么提交 Pull Request(下面簡稱 PR )。
在閱讀本文前,希望你已經具備以下條件:
已經安裝好 Git,能夠用命令行進行基本的 Git 操作。如果不熟悉 Git,你可以看一下廖雪峰的 Git 教程;如果你對自己的英文有自信,那么 Learn Git Branching 這個互動教程一定會讓你受益更多!
已經注冊一個 GitHub 帳號,并對 GitHub 的一些基本概念(例如倉庫,Issue,還有我們討論的核心 PR)有所了解。
擁有一顆在開源社區呼風喚雨的雄心壯志(手動滑稽)。
尋找值得解決的 Issue
通常,貢獻的第一步是尋找值得解決的 Issue。選擇正確的 Issue 并不簡單,除了力所能及,還要看一下有沒有人已經在解決這個問題。你可以看一下這個 Issue 是否有人已經回復打算解決,或者在 Pull Requests 列表中搜索一下有沒有人已經在解決,否則真的就是在浪費寶貴的時間。
選擇合適的 Issue
這里我們選擇解決 rational-numbers: implement exercise,任務就是實現一個新的練習,名為 rational-numbers。之所以選擇這個 Issue,是因為倉庫維護者很認真地把實現新練習的詳細步驟都告訴了我們,而且也沒有其他人領這個任務。于是我們回復一句“I'll work on this”,既是通知維護者,也是告訴其他人我們已經負責解決這個 Issue,請不要重復勞動。
好了,開始動手吧!
準備工作
第一步:Fork原倉庫
在頁面右上角點擊 Fork 按鈕,隨后就生成了屬于你的倉庫。
上圖:Fork 原倉庫
上圖:Fork 來的倉庫
為什么要先 Fork 別人的倉庫呢?不能直接把 exercism/python 直接 clone 到本地嗎?
如果你只是打算閱讀別人的源代碼,這樣做當然是可以的,然后每次你只需要 git pull 就可以獲取最新的代碼了。但如果你打算貢獻代碼就不能簡單地 clone 了。由于你不具備 exercism/python 的 write access(寫入權限),因此你就無法使用 git push 來推送你的修改,這時候就只能 Fork 到自己的帳號下,GitHub 會為你生成 mRcfps/python(mRcfps 是我的 GitHub 用戶名)。對于這個 Fork 來的倉庫,你就擁有了所有的權限(克隆、修改甚至是刪除倉庫)。這時候就可以進行任何想要的修改了。
第二步:將 Fork 來的倉庫 clone 到本地
在命令行中輸入下面的命令:
$ git clone https://github.com/mRcfps/python.git第三步:創建新分支
GitHub Flow:創建新分支階段
這一步是最容易被忽視的一步,卻恰恰是正式開始貢獻的第一步。
?
$ git checkout -b impl-rational-numbers這里我創建了一個新的分支 impl-rational-numbers,意思就是 implement (exercise) rational numbers。在創建分支時要盡量保證易于記憶、易于辨認,這樣做有兩點好處:
- 在多個分支上切換工作時會方便很多
- 在提交 PR 后便于倉庫主進行維護
一個需要思考的問題是,為什么需要開新的分支?不能直接在 master 分支上修改嗎?
先給出簡單的回答:能,但是非常非常不推薦。
根據 GitHub Flow 的定義,master 分支應當確保始終是可部署的(deployable),所以在 master 分支上進行開發和嘗試是非常不推薦的做法。而且 GitHub 的 PR 都是以分支為單位的,如果你選擇 master 分支進行開發,那么當你想要解決另一個 Issue 的時候就會變得非常棘手(熟悉 Git 的朋友也許會說可以通過回退節點再開新分支,但是那樣分支管理就會變得一團糟)。
貢獻代碼
GitHub Flow:貢獻代碼階段
這里就不展示全部的工作了,具體代碼變化請參考這里。
?
$ git status On branch impl-rational-numbers Changes not staged for commit:(use"git add <file>..."to update what will be committed)(use"git checkout -- <file>..."to discard changes in working directory)modified: config.jsonmodified: exercises/rational-numbers/example.pymodified: exercises/rational-numbers/rational_numbers.pymodified: exercises/rational-numbers/rational_numbers_test.pymodified: exercises/rational-numbers/README.mdno changes added to commit (use "git add" and/or "git commit -a")好的,然后我們進行 commit:
?
$ git commit -am "rational-numbers: implement exercise"提交工作
GitHub Flow:提交 PR 階段
接下來就是激動人心的時刻:提交我們貢獻的代碼!
首先,我們需要把修改提交到 mRcfps/python ,也就是我們自己的遠程倉庫。
?
$ git push -u origin impl-rational-numbers選項 -u 等同于 —set-upstream。impl-rational-numbers 就是我們剛才進行修改的分支。然后,我們打開 mRcfps/python,也就是我們 Fork 來的倉庫,會看到一點小小的變化:
Fork 來的倉庫自動檢測到新提交的分支
實際上如果你打開 exercism/python 的頁面也會出現這樣的提示。然后點擊按鈕 Compare & pull request,開始編輯我們的 PR:
編輯 PR 信息
這里要說明一下 GitHub 關鍵詞:當使用 fix(es),close(s) 或 resolve(s) 時,如果這個 Pull Request 被合并,會自動關閉對應的 Issue。這里我標出了 Closes #1300,那么當我們貢獻的代碼被接受時,就會關閉 rational-numbers: implement exercise 這個 Issue。正確地使用 GitHub 關鍵詞能夠極大地方便倉庫維護者,他們就不需要去查找對應的是哪個 Issue 并去手動關閉它了。
點擊 Create pull request,進行提交!
討論和評審
GitHub Flow:評審討論階段
接下來就是等待。第二天起來發現倉庫維護者回復我們了。
維護者進行了代碼評審
他指出我們修改的 config.json 有問題,并給出了修改建議。至于他手抖一不小心 approve 我們的修改就不必在意了(再次手動滑稽)。
按照他的建議修改好之后,我們提交新的修改。
?
$ git commit -am "rational-numbers: fix topics in config.json" $ git push可以打開 PR 頁面查看我們新的修改。
新的修改出現在 Pull Request 頁面
部署階段
GitHub Flow:部署階段
倉庫維護者同意了我們的修改!
維護者部署了我們的修改
然后他將 exercism/python 的 master 分支并入了我們的 impl-rational-numbers 分支。他為什么要這么做呢?因為當我們在這個分支上工作時,exercism/python 的 master 分支上可能提交了新的修改,導致我們的分支并不是最新的。
master 上新的修改使我們的分支過時
通過將 master 分支并入我們的分支,我們的分支就能進入即將部署(Ready to Deploy)狀態了。如果這時候 CI (持續集成,會在后面講到)報錯,這就說明我們的分支還不能部署,還需要進一步修改甚至是回滾。但是這里,我們合并后的分支通過了 CI 的測試。
合并階段
GitHub Flow:合并階段
維護者緊接著就將我們的分支正式并入了 exercism/python 的 master 分支,這意味著我們的 PR 畫上了圓滿的句號,我們的貢獻真正地進入到了原倉庫!
維護者合并了我們的分支
由于 impl-rational-numbers 已經合并,可以安全刪除,所以我們點擊 Delete branch 按鈕,刪除我們遠程倉庫 mRcfps/python 中的分支。然后在本地輸入下面的命令,刪除本地分支:
?
$ git checkout master $ git branch -D impl-rational-numbers這里為什么使用 -D 進行強制刪除呢?因為 impl-rational-numbers 在本地并沒有與 mRcfps/python 的 master 分支合并(不要繞暈了,剛才我們只是和 exercism/python 的 master 進行了合并)。我們自己的 master 分支推薦用下面介紹到的方法進行同步。
一些補充
關于 PR 生命周期的介紹就到此結束了。接下來我會講一些相關的較為重要的地方。
保持 Fork 來的倉庫同步
如果其他的貢獻者向 exercism/python 提交代碼,或者是我們自己提交的代碼,我們的 mRcfps/python 就會過時。要經常保持我們 Fork 來的倉庫與原倉庫同步,這樣能盡可能地降低沖突發生的概率。接下來還是以我們 Fork 來的倉庫 mRcfps/python 為例,來與 exercism/python 保持同步。
首先,查看 mRcfps/python 有哪些遠程倉庫。這里應該只有 origin。
?
$ git remote -v origin https://github.com/mRcfps/python.git (fetch) origin https://github.com/mRcfps/python.git (push)然后,將 exercism/python 添加進我們的 remote 倉庫中,將其命名為 upstream(當然也可以取其他名字,但是按照慣例會更加方便)。
?
$ git remote add upstream https://github.com/exercism/python.git再看看 remote 列表中是不是多了些什么……
?
$ git remote -v origin https://github.com/mRcfps/python.git (fetch) origin https://github.com/mRcfps/python.git (push) upstream https://github.com/exercism/python.git (fetch) upstream https://github.com/exercism/python.git (push)upstream 已經在 remote 列表中!然后我們就可以輕松地進行同步了。先確保當前處在 master 分支上,然后獲取 upstream 的修改,再并入我們本地的 master 分支。
?
$ git checkout master $ git fetch upstream $ git merge upstream/master再把本地的更新 push 到 origin,也就是我們的 GitHub 倉庫:
?
$ git push同步工作完成!
持續集成
很多開源項目都會通過持續集成(Continuous Integration,簡稱 CI)來確保代碼質量。對于我們貢獻者來說,這意味著每次提交 PR 和繼續 push 代碼,CI 都會對我們的提交進行構建并執行倉庫維護者指定的檢查,例如代碼風格檢查、單元測試等等。
如果你查看你新提交的 PR,你會發現右上角有個黃色的圓圈,這表示 CI 正在檢查你的提交。
CI 正在檢查我們的 PR
當右上角的黃色圓圈變成綠色的勾,就表示你的代碼通過了 CI !
這個 PR 通過了 CI
有時候會出現紅色的叉,表示未通過 CI 測試。
這個 PR 未通過 CI
這時候我們就需要進入 PR 頁面,翻到最下面,查看 Travis-CI (這個倉庫使用的是流行的 Travis CI)檢查的詳細信息,找出錯誤原因后進行修改,然后 git push 提交我們的修改即可,直到通過 CI。
總結
可能步驟有點復雜,所以這里總結一下 Pull Request 的生命周期 :
確定要貢獻的項目,尋找值得解決的 Issue。
將原倉庫 Fork 到自己的帳號下,然后克隆到本地。
?
$ git clone https://github.com/<YOUR_USERNAME>/<FORKED_REPO>.git?
$ git checkout -b <NEW_BRANCH_NAME> $ git commit -am "<COMMIT_MESSAGE>" $ git push -u origin <NEW_BRANCH_NAME>打開倉庫的 GitHub 頁面,點擊提示的 Compare & pull request 按鈕,填寫 PR 信息(記得使用 GitHub 關鍵詞關閉對應的 Issue)然后提交。
如果 CI 測試未通過,或者倉庫維護者要求修改(request changes),那么就在本地繼續修改代碼,然后 git push 再次提交,直到通過 CI 和倉庫維護者的評審。
倉庫維護者部署和并入你的分支,貢獻完成。
親自實踐
這篇文章的 GitHub 倉庫在這里,你可以隨意地發起 Issue 或 Pull Request。如果你只是想要親自實踐一下上面所講的內容,就請在 THOUGHTS.md 中隨意寫下你的想法并提交給我,我會盡快合并你的分支。當然如果你對本文有改進意見,那更歡迎你的 Pull Request,讓這篇文章變得更好!
作者:圖雀社區
鏈接:https://www.jianshu.com/p/ac33f0295629
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的【转】GitHub 从单机到联机:玩转 Pull Request的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LCD越来越不香了!三星和LG果断砍单
- 下一篇: 【转】Dynamics 365中的事件框