前一陣國內使用者濫用 Issue 的事件已逐漸平息,風波過後,留給我們一些思考:我們該如何參與並回饋這類全球開源社群?
作為一個在 GitHub 浪跡多年的人,我來談談自己的心得體會,希望能幫你避免再次踩坑。
【作為遊客】
當你訪問一個倉庫的時候,會遇到三個按鈕:Watch(關注) / Star(星標) / Fork(分支)。
Watch 表示你對這個倉庫中發生的事件感興趣,比如出現了新的 issue 等。當這些事件發生時 GitHub 就會自動給你一個頁面通知,並往你的註冊郵箱傳送一封郵件,當然,你也可以在 通知設定 介面禁止這些通知。當你 watch 很多倉庫的時候,通知郵件可能會把你的郵箱塞滿,這時候,除了在自己的郵箱設定規則之外,也可以來這裡禁用通知。
Star 表示特別標記這個倉庫,這和郵箱中的 Star 是一樣的。嚴格意義上,它只是你個人需要經常訪問它而進行的快捷標註,這樣你就能通過 Your stars 頁面(比如我 Star 過的專案)來快速找到這些專案了。它經常被用做表達支援的投票,官方也提倡如此,不過我很少會這麼做。
Fork 有兩種用途:一種是你要參與它,為它提交程式碼,這部分我會在稍後的【作為貢獻者】部分細講;另一種是覺得這個倉庫可能會被原作者刪掉,因此 Fork 出來一份,這樣即使作者刪掉了,我這裡也有一個 Fork 那個時間點的版本的快照。不過要注意,Fork 出來的版本是不會隨著原始倉庫而自動更新的。理想情況下,後一種情況該算誤用,因為已經開源出來的程式碼原作者是不應該刪除的,但是確實有過被刪除的情況。所以有時候我會把 Fork 但不打算髮 PR 的行為看作是對庫作者的不信任投票。當然,大多數的倉庫作者可能不會這麼想。
【作為貢獻者】
貢獻的形式有兩種:提 issue 和 提 pull request,這兩者有一些共同的要求,包括:
- 認真看並遵循對方給出的 issue 模板 / PR 模板。
- 及時跟進,當對方有回覆時應該儘早給出足夠明確的回答。如果覺得對方的答覆已經解決了你的問題,或者這個確實不是問題,就及時關閉,不要等作者動手。
- 大多數倉庫都要用英語提,但專門面向中文使用者的倉庫是例外。其實這一點並沒有想象中的那麼難,現在的 Google Translate 已經非常強大了,而且 https://translate.google.cn 不用翻牆也能訪問,只要寫好中文,然後在裡面翻譯成英文,再修正一下英文翻譯就可以了。
接下來我再分別細說一下它們。
提 issue 也就是提問題,可以再細分為兩種:提 BUG 和 提需求(Feature Request / Proposal)。
提 BUG 的基本要求是確認它是問題並把問題說清楚。
開源作者都很忙,大多數人都不會有時間跟你來回溝通,不願意花很長時間卻只是為了把問題問清楚。如果最後經過很長時間的嘗試之後發現根本不是問題,那作者是會非常失望的 —— 如果不是憤怒的話。
所以,如果你發現了一個問題,請先在心裡告訴自己這是“疑似問題”,然後用不同的專案甚至不同的環境來嘗試重現它,這些過程你都要記錄下來。等你確認了它真的是問題之後,再去提 issue,並且把你的這些嘗試過程及其結果和你期待的結果都包含進去。同時,最好把這些嘗試過程中的建立專案都上傳到 GitHub 上的個人空間,讓作者可以直接拿它重現你的問題,而不用自己重建環境。這些工作對作者關注你這個問題並解決它是非常重要的。
注意,如果你只是單純的不會用,而不是發現了程式碼本身的 BUG,那麼請不要提 issue。因為 issue 並不是用來請教作者的直通車,你應該去 Stackoverflow 之類的專業問答網站提問。很多開源倉庫的作者也同時活躍在 Stackoverflow 等問答網站,所以不用擔心得不到專業的答覆。
提需求的基本要求是要能坦然接受別人的拒絕。
每個開源軟體都有自己的發展計劃,對於比較火的專案,你提出的特性請求能有 1% 的概率被接受就不錯了。你要做的是要儘可能在第一帖中就把這個請求的來龍去脈說清楚,如果發現作者對你的需求有誤解,那麼可以回帖解釋,但不要胡攪蠻纏、強詞奪理。如果覺得對方拒絕得有理,請表示感謝並主動關閉你的特性請求。
提 Pull Request(簡稱 PR)也就是申請往主庫中合併程式碼,是個技術含量較高的工作。
提 PR 的前提是先 Fork 對方的倉庫,而不要 clone 下來然後上傳到自己的倉庫,那樣的話 GitHub 沒法知道這倆庫是同源的。
Fork 之後,你的個人倉庫中就有了一個分支倉庫,你可以往這個分支倉庫中提交程式碼,覺得達到了 PR 的預定目標之後,就推送它,並回到 GitHub 頁面中發起 PR(GitHub 會在頁面上主動提示可以發 PR,跟著走就行)。
提 PR 的基本要求是達到對方的程式碼質量標準。如果對方的倉庫單元測試覆蓋率很高,那麼你也要確保自己提交的程式碼有足夠的測試覆蓋率。如果對方要求在程式碼中使用內聯註釋來生成文件,那麼你也要寫好相應的文件註釋。如果對方對程式碼格式的要求很嚴格,那麼你也應該遵循它。當然,較好的開源倉庫通常都會有相應的工具進行檢查,如果通不過就會標記出來。
如果你這個 PR 已經過時了,那麼可以有兩種選擇:如果對方的新版本已經解決了這個問題,請主動關閉你自己這個;如果仍然有這個問題,請在本地把你的倉庫 Rebase 到對方的最新版本,解決了衝突,然後再推送到自己的倉庫,你推送完之後,對方的 PR 流中就會自動反應這些更改,而不用你關閉 PR 再重新提起(我提第一個 PR 時就曾幹過這樣的傻事)。
如果對方回覆了你的 PR,要求你做某些修改,如果覺得合理,那就照著修改,覺得不合理,可以繼續討論,闡明你的觀點。但通常來說對方比你經驗豐富,水平也可能更高,請先仔細思考一下其合理性再回復。
【作為作者】
作為倉庫的作者,首先要在倉庫中包含一個明確的 LICENSE 檔案。
通常程式碼類的倉庫會選擇 MIT 等比較開放的協議,如果你是開源狂熱者,也可以選擇 GPL 等比較激進的協議,但是要注意原則上 GitHub 不允許開放倉庫中的程式碼使用私有/純商業授權協議。是否法律上不允許我沒仔細分析過,不過至少道德上是不允許的。同時,已經用 MIT 等開源協議開源的既有程式碼在法律上是不允許再閉源的,也就是不能溯及既往。比如你的 1.0 是 MIT 協議,那麼別人就可以永遠按照 MIT 來使用 1.0 版本的程式碼,但是你可以把 2.0 改成別的協議甚至退出開源(GPL是例外,一旦開放永不關閉)。不過即使如此,別人也仍然可以按照 MIT 來隨意使用 1.0 的程式碼。
文件類的倉庫通常會選擇 CC 或 CC-BY-NC 協議,兩者的區別是前者允許商用,後者不允許商用或商用時需單獨授權。
其次,要提供 CONTRIBUTING.md 貢獻指南等輔助檔案,指導開發者如何做出貢獻。如果你要為 issue 和 PR 提供模板,可以在倉庫中包含一個 .github/ISSUE_TEMPLATE.md
和 .github/PULL_REQUEST_TEMPLATE.md
檔案,這樣別人要參與時就會先看到這個模板中的內容,避免他們誤用。
最後,如果已經對外宣傳或者有很多人關注了,就不要輕易棄坑,要堅持下去,如果實在堅持不下去了,請移交給別人。這是開源作者的責任。當然,沒有推廣過的嘗試性專案不必受此限制。不過,除非萬不得已(比如安全問題),否則不要刪除你已經開源的倉庫,那樣做很不禮貌,必要時你可以廢棄它,並寫一個 README 來告訴讀者去哪裡找搬家後的版本。
【結語】
記住:開源是一種信仰,而不是應聘的敲門磚或者賺 KPI 的工具。非要那麼做固然也不是不可以,但請別忘了初心,一旦有條件了,就要用各種形式回饋開源社群,這才是開源社群繁榮的根本。