天天看點

如何管理一個大型開源倉庫?淘系帶你一探究竟

如何管理一個大型開源倉庫?淘系帶你一探究竟

作者|劉雄(大果)

出品|阿裡巴巴新零售淘系技術部

導讀:對于每個開發者來講,git 倉庫是我們幾乎每天都要接觸的東西,但是實際上大多數的 git 倉庫管理都是非常随性且不規範的,在某些情況下這樣做并沒有太大的問題,但是當協作成員逐漸增多、倉庫職責逐漸擴充時,很多原本不規範的小問題會被逐漸放大乃至産生一些極為嚴重的問題。本文将為大家介紹在管理過程中的實踐經驗。

作者所在的飛冰(ICE)團隊在 2018 年 2 月開源了 alibaba/ice 這個倉庫,經過不到一年的時間終于在 2018 年末達到了 1w+ stars 的裡程碑,在管理這個倉庫以及營運社群的過程中我們積累了一些或大或小的最佳實踐,希望能分享出來幫助到其他開源或者沒開源的 git 倉庫管理者。

合理的拆分倉庫

當我們說管理倉庫的時候,其實面向的不是一個單一的倉庫,而是一個産品、一個項目甚至一個業務,這背後可能會有多個倉庫也可能隻有一個倉庫,是以在前期的規劃上要盡量梳理清楚,核心避免兩個誤區:

誤區 1:每個職責都建一個倉庫

這個方案可能是多數人的直覺反應,但是這種方式會讓産品對應的倉庫數快速增多,導緻長期管理成本陡增:

  • 倉庫權限管理成本高且容易混亂
  • 代碼開發送出成本高
  • issue/PR 太過零散,難以統計管理
  • ……

實際上,飛冰(ICE)原先在内部的時候,我們開發了很多業務元件,每個業務元件都是一個單獨倉庫,然後最近在做統一更新(工具、規範或者其他變更導緻)的時候給我帶來非常大的困擾:

  • 有的元件(倉庫)已經不再維護但沒有任何标記
  • group 權限管理太過松散導緻出現一些跟官方無關的元件
  • 更新過程中需要頻繁切換倉庫操作

是以,我們需要避免過于零散的管理方式,結合實際場景做适當的聚合。

誤區 2:所有的職責都用一個倉庫承載

在前端社群裡,随着 lerna 這個批量釋出包工具的出現,這種方式越來越流行,一些非常熱門的項目比如 babel、React、jest 等都逐漸遷移到這個方案。先抛開 lerna 這個工具提供的能力,這種聚合式的管理方式給倉庫管理者節省了很多成本,比如:

  • 隻需要管理一個倉庫
  • issue/PR/wiki 等都收斂到一個地方管理

但是在實踐這種方式的時候有可能會走偏,還是以我所在的 ICE 團隊做反面教材,踩了誤區 1 的坑之後,在做開源版本的時候我們果斷把所有包都放到同一個倉庫,然後通過目錄結構來保證職責清晰,這個方式也同樣如上面所提到的給我們的管理帶來了諸多便利,但在經曆了一年的疊代之後目前也遇到了一些問題:

  • 職責多代表代碼多,然後随着曆史記錄的增長,倉庫 clone 速度一日不如一日,尤其在一些小公司的慢速網路環境下(即便加了 --depth)
  • 目錄結構較為複雜,對有心貢獻代碼的社群同學不夠友好

是以我們推薦「在方案 2 的基礎上按照職責再做一層拆分」,結合 alibaba/ice 這個倉庫,我們已經通過職責将 ice-devtools/ice-scripts/react-materials 等拆為獨立倉庫,這些倉庫職責上足夠清晰同時相關依賴聚合在一起不至于太過分散。

建立團隊内的操作規範

筆者曾經有幸參與過淘寶前端團隊的代碼規範制定以及相關工具落地,是以深知規範之于團隊的重要性,同時也有一些制定規範的原則:

(1) 規範首先保證正确,其次提升品質;

(2) 規範不能過多影響到效率(兩者的權衡需要結合實際場景)。

以下就是我們目前在遵循的一些規範:

保護分支!

如何管理一個大型開源倉庫?淘系帶你一探究竟

根據倉庫情況設定保護分支,禁止直接往保護分支送出代碼,在非常特殊的情況下 admin 賬戶可以繞過。

建立分支規則

如何管理一個大型開源倉庫?淘系帶你一探究竟
  • 分支名稱需要有語義,比如 ice-scripts/fix-foo-bug
  • 如果需求比較簡單,時間周期比較短,那麼直接從 master 切一個分支,然後通過 PR 合并後到 master,合并之後釋出對應包的版本
  • 如果需求包含多個變更點,比如 iceworks 釋出版本,往往涉及到多個功能點,開發周期一般會在一周左右,如果每個 PR 都往 master 上合并,很難把控整體的進度。是以我們有以下約定:

a.先從 master 切出 release 分支(如 release/iceworks-2.16.0),然後提一個基準 PR,PR 中需要補充目前版本包含的功能清單以及釋出先後順序等,該 PR 主要用于管理此次版本開發進度,release 分支不允許直接推送代碼,同時合并到 master 時也無需 Review

b.然後每個功能變更都從 release 分支切出新分支,同時 PR 也需要合并到對應 release 分支,切出的分支不需要包含版本資訊(比如 iceworks/fix-xxxx 即可)

c.等所有 PR Review 完成并且合并到 release 分支之後,在 release 分支進行釋出,釋出完成後再将 release -> master 的 PR 合并(此處不在 master 分支釋出的原因是擔心釋出時可能會出各種問題,需要再次做代碼變更)

commit message 規範

如何管理一個大型開源倉庫?淘系帶你一探究竟

好的 commit message 可以讓人快速了解代碼意圖,加速 review 程序,未來對于整個代碼倉庫的曆史追溯也會更加友善,關于這一點社群有足夠多的規範可以參考,此處不再一一贅述,有興趣可以參考末尾的參考連結。

PR 合并流程

如何管理一個大型開源倉庫?淘系帶你一探究竟

github 預設提供了三種合并 PR 的方式,關于三種方式的差別可以參考文末的相關連結,我們認為大多數情況應該選擇 Squash and merge,因為 squash 會将目前 PR 的多個 commit 合并,讓整個送出曆史更加幹淨清晰。但是在将上文提到的 release 分支合并到 master 時建議使用普通 Merge,是以此時我們需要保留那些有效的 commit 記錄。同時在合并 PR 的時候 Reviewer 有責任重新編寫 commit message 以保證語義更加準确。

這裡簡單追溯一點曆史:在最早期的時候,github 還沒有提供 squash merge 的方式,當我們向開源倉庫送出一個 PR 時,在倉庫作者 review 完成之後一般會要求送出者将 commit 合并,是以很多人都有谷歌過「如何合并 commit」這樣的關鍵詞,而如今隻需要點一下按鈕即可,這也是工具對效率提升的一個展現。

釋出流程

對于管理工具包的同學,都應該熟悉并且遵循 Semver 規範(語義化版本),這是原則,在此基礎上需要遵循以下規範:

測試版本:版本号需要遵循 x.y.z-n 的規則,通過 npm publish --tag beta 釋出,很多同學包含筆者本人經常會忘記 --tag beta,不知道有沒有更加有效的方式限制?

正式版直接通過 npm publish 釋出

正式版本釋出之後,需要同時建立對應的 git tag,tag 命名規則:産品名/x.y.z,比如 ice-scripts/1.0.2,然後在 GitHub 上填寫 Release 資訊

其他

如何保證規範落地

結合曾經在淘寶前端團隊推動的規範落地以及當下在 ICE 團隊制定的規範,兩點結論可供參考:

  • 規範需要保證多數人認可,然後由松到緊逐漸疊代,人跟着規範逐漸成長
  • 小團隊靠素養,大團隊靠工具:在小團隊内制定規範,需要做的就是反複強調,逐漸讓每個人形成習慣;而在大團隊裡顯然是沒法關注到每個人的,此時需要借助工具,比如 eslint,commit-check 以及像門神這種強流程的工具

如何疊代曆史版本

上文說的一些工具包的發版,假設我有一個工具包 ice-scripts 在 1.6.5 的基礎釋出了一個 break change 的版本 2.0.0,正常情況下我們肯定是在 master 分支(2.0.0 的代碼)的基礎上逐漸疊代,但 1.x 的版本可能還有使用者使用,當我們需要修複 1.x 的一個 bug 時如何去做?這裡推薦一個流程:

首先基于 git tag ice-scripts/1.6.5 切出一個 stable/ice-scripts-1.x 的分支(幸虧之前打了 tag,否則要找到對應的 commit 還是有點工作量的)

将 stable/ice-scripts-1.x 設為保護分支,可以了解為 1.x 版本的 master 分支

從 stable/ice-scripts-1.x 切出新分支 ice-scripts-1.x/fix-bar,然後修改代碼送出 PR 到 stable/ice-scripts-1.x 分支上

Review 完成後合并代碼,然後在 stable/ice-scripts-1.x 分支上進行釋出

如何做好答疑

營運社群的過程一定需要頻繁面對使用者的疑問,如何在滿足使用者的同時又能保證自身投入不影響到正常工具顯得極為重要了,對于技術産品,根據面向使用者群體的不同目前兩種主流答疑方式:

  • GitHub issue: 純異步交流,保證所有問題讨論都能沉澱下來,同時因為異步溝通有成本,大家會努力一點表達清楚自己的意圖,相對來講溝通品質更高,但響應速度之類的無法保證
  • 類釘釘群:同步交流,響應速度快,但是對于維護者來說時間容易被打碎,降低工作效率

如何管理 issue

結合治理 ICE 的曆史 issue 提供一些建議僅供參考:

  • 通過 issue 模闆提升 issue 品質:ICE 倉庫裡早期的 issue 品質非常低,很多問題都無法複現
  • 基于産品緯度建立對應的标簽分類,每個 issue 關聯标簽,然後由對應負責人統一處理
  • issue 不要求及時處理,但鼓勵能通過溝通或其他方式快速明确問題,防止時間長了不了解 issue 的描述然後又無法跟 issue 作者溝通

如何營運社群

ICE 團隊目前維護着 6 個釘釘答疑群(每個 1000 人)以及技術論壇的官方帳号,但整體活躍度都比較一般,目前無論是精力上的投入還是營運産品的經驗都比較缺失,希望能得到一些建議或者支援。

有趣的機器人

github 上有很多友善的機器人(or App?),這裡推薦個人覺得比較有用的兩個機器人:

  • delete-merged-branch:合并 PR 之後會自動删除對應分支,防止無用分支的堆積
  • Weekly Digest:每周建立一個 issue,彙總倉庫一周内的動态,比如:新增了哪些 issue/PR,有哪些人 star 了倉庫等,示例 Weekly Digest (30 December, 2018 - 6 January, 2019)「 https://github.com/alibaba/ice/issues/1264

今日話題

你認為還有那些有趣的機器人

歡迎推薦

對于 git 的操作,如果有不同的見解

歡迎評論區留言探讨

小編将針對有趣有價值的留言送出「淘系定制公仔1個咯」

相關連結

alibaba/ice 官方倉庫

https://github.com/alibaba/ice

寫出好的 commit message

https://ruby-china.org/topics/15737

5.1 代碼合并:Merge、Rebase 的選擇 (

https://github.com/geeeeeeeeek/git-recipes/wiki/5.1-%E4%BB%A3%E7%A0%81%E5%90%88%E5%B9%B6%EF%BC%9AMerge%E3%80%81Rebase-%E7%9A%84%E9%80%89%E6%8B%A9

Semver 規範(

https://semver.org/lang/zh-CN/