Last Updated on 2023-12-13 by Clay
介紹
在 GitHub 上發 Pull Request (PR) 給開源項目是一件美好卻又重要的事情。簡單來說,PR 是一個當你看到開源專案時,發現有個真的很想做的功能/很想修復的 BUG,你可以嘗試將該開源專案分岔(fork)成自己的私有專案,並在上面進行開發;開發完成後,再藉由提交 PR 給原始的專案維護者做合併檢查,看是否要合併回原始專案的主分支。
若是成功被接受,你就是成功為這個開源專案添加了新的功能或是解決到問題。大家一起來做,才會讓這個項目發展得更快。
仔細想想,開源(open source)項目的優點不就是讓任何人都可以參與、貢獻在這個項目中嗎?也即是說,若是願意發 PR 給開源項目,意味著無私地貢獻自己的能力去完善該項目中的某項功能、或是修復 BUG,讓更多人在使用這個項目時有更好的體驗,這真的是一件很棒的事情!
最近,我嘗試第一次提交 PR 給了不是大學專案、不是公司同仁的開源專案,新增了一個我認為很有幫助的功能,並且很榮幸地被合併進 master/main 分支了。對我來說真的是一次收穫滿滿的經驗。
於是,我也希望把提交的流程完整紀錄起來,希望這次的 PR 提交經驗不要只是曇花一現,並且讓我自己下次重讀我這篇筆記的時間,就是在不遠的將來。
提交 PR 的流程紀錄
以下簡單地進行摘要式紀錄:
- 確認 Issues 和 PRs 中有無跟你相同問題或是意見,並確認維護者的對於這個意見的想法
- 閱讀該項目的貢獻指南
- Fork 到自己帳號,並 Clone 項目當自己本地端
- 設置開發環境
- 建立新的分支
- 著手開發功能 / 修復 BUG
- 編寫單元測試
- 編寫說明文件
- Commit 修改
- 提交前,最後一次同步上游最新版本
- Push 到自己 Fork 的專案
- 建立 Pull Request
- 程式碼審查
- 合併
- 刪除自己在開源項目的分支
以下,我再更進一步地解釋要做的內容。
1. 確認 Issues 和 PRs 中有無跟你相同問題或是意見,並確認維護者的對於這個意見的想法
在看到開源項目中有自己想要添加或修改的功能前,別忘了先確認一下 Issues 和 PRs 中是不是已經有人提出過類似的看法了?如果有,可以參考一下他們的意見,或是確認一下維護者對於這個修改的態度。
有時候,他們可能已經對你想要貢獻的功能有所安排、甚至是開發到一半,所以先瀏覽一遍總是沒有錯的。
就算你沒有看到與自己相同的想法,在開始正式開發前,也最好先禮貌性地發個 issue 詢問維護者與社群,取得他們對於你想要貢獻的功能的反饋。
不過開源社群大多數時候都很友善,所以放心大膽問沒有關係。大多數人其實都很喜歡談論自己的開發工作的。
2. 閱讀該項目的貢獻指南
許多開源項目都會有自己的一份貢獻指南(Contribution Guideline),其中可能會規範 PR 的形式、哪邊會收集待開發的新功能,以及統一的 coding style、提交流成、單元測試... 等等要求。在開始準備提交自己想要的功能前,別忘了先瀏覽一下這份文件。
3. Fork 到自己帳號,並 Clone 項目當自己本地端
在 GitHub 上,將你想要貢獻的專案 Fork 到自己的帳號底下,接著再 Clone 自己 forked 的專案到自己的本地端。
4. 設置開發環境
根據項目文件的說明建立一模一樣的環境。除了特殊情況外,千萬不要使用自己的特規環境去開發別人的專案再要求別人配合自己。
5. 建立新的分支
在本地 repo 依照想要新建的功能建立新的分支,當然理論上最好的作法就是開發什麼功能都要分出恰當的分支就是了。不過,這樣做的好處是讓我們的修改可以與主分支錯開,方便管理與審查。
git checkout -b new-feature-branch
6. 著手開發功能 / 修復 BUG
到了這裡,終於正式開始開發新功能或修復 BUG 了!別忘了,要符合該開源項目的 coding style 與其他規定。
7. 編寫單元測試
如果項目有要求,別忘了依照指示建立單元測試並確保都能順利通過。如果項目沒有額外要求,也別忘了自己測試原先的功能是否完好、自己新增添的功能是否能正常工作。
8. 編寫說明文件
更新或編寫相關的說明文件,通常是 README.md,說明你所添加的新功能以及該如何使用。若是修復 BUG 則通常不需要特別修改這份文件,而是反應在 issues 或是提交時的說明。
9. Commit 修改
將自己的修改過的文件提交到自己的分支上。確保提交的訊息是清晰並能夠說明你的更新的。
git add updated_file
git commit -m "your message"
10. 提交前,最後一次同步上游最新版本
在提交前,同步開源項目主分支的最新修改,以確保程式碼能夠兼容該項目的最新進度。
我們可以透過 git remote -v
來確認遠程項目設置,如果遠程項目中沒有設置到原先的開源專案,則可以自行添加。
git remote add upstream https://github.com/original_owner/original_repo.git
在這裡,upstream 是我們自己定義的,代表原先開源項目,而後方的專案則是原始項目的 URL。
有了之後,我們就能獲取 upstream 的最新更新。
git fetch upstream
確認沒有問題後,可以依據自己的需求將其合併到本地端的主分支(main / master)。
git checkout your_branch
git merge upstream/your_branch
如果想要提交清楚的歷史,則可以使用 rebase
。
git checkout your_branch
git rebase upstream/your_branch
11. Push 到自己 Fork 的專案
最後,再將其提交到自己 forked 的遠端 GitHub 項目。
git push origin new-feature-branch
12. 建立 Pull Request
這時候,如果你回到原本的開源項目頁,點擊 Pull requests 分頁,你應該會看到 GitHub 自動偵測到你有可以發送 PR 的分支,點擊綠色的 Compare & pull request 按鈕即可發送你的 PR 請求。
這裡別忘了詳細說明自己 PR 的功能與用意,這才能更好地讓維護者知道你的貢獻何在。
13. 程式碼審查
接著我們可能會跟維護者有幾次的討論,根據維護者或是社群成員的意見進行必要的修改。
14. 合併
一旦 PR 順利被同意,則項目維護者會將合併我們提交的程式碼到 main/master branch 上。
15. 刪除自己在開源項目的分支
這一步其實是 optional 的,看過許多人提交完之後其實並沒有刪除自己在開源項目的分支 —— 不過 GitHub 官方推薦的最佳實踐步驟是要去把自己的分支刪除掉。
來到自己已經合併的提交 PR,你應該會在 Closed 裡面找到它,你應該會看到 GitHub 自動提示的 Delete branch 按鈕。
寫了一大串我做過的筆記紀錄,其實無非也僅僅只是希望自己與大家都能盡情地貢獻自己的程式能力與技術到各個開源專案中,希望能幫助到大家與自己。