在版本控制系統中,Monorepo(“mono”意為“單一”,“repo”是“存儲庫”的縮寫)是一種软件開發策略,其中多個项目的代码存儲在同一個代码仓库里面。 這種做法至少可以回溯到 2000 年代初期,當時這種做法通常被稱為共享代码库。 Google, Airbnb, 以及Twitter 所有這些公司都採用非常大的单一仓库(Monorepo),採用不同的策略來擴充具有大量代码和日常改版的建置系統和版本控制工具。
一個相關的概念是龐大应用程序,但是龐大应用程序將其子项目組合成一個大项目,而單一存儲庫(Monorepo)可能包含多個獨立项目。
優點
與個體存儲庫相比,單一存儲庫有許多潛在優勢:
; 方便重複利用代码
: 類似的功能或溝通協定可以抽像到共享工具庫中並直接包含在项目中,而不需要依靠套件管理器。
; 簡化相依性套件管理
: 在多個项目依賴於第三方相依性套件的多存儲庫環境中,該相依性套件可能會被多次下載或構建。在 monorepo 中,可以輕鬆優化構建,因為所引用的相依性套件都儲存於同一代码庫中。
; 原子化提交(Atomic commit)
: 當一起運作的项目包含在單獨的存儲庫中時,發布需要同步一個项目的哪些版本與另一個项目一起運作。在相當龐大的项目中,管理相依套性件之間的相容版本可能會變成相依套件地獄(Dependencies hell)。在 monorepo 中,這個問題可以被解決,因為開發者可以原子化的方式修改多個项目。
; 大規模代码重構
: 由於開發者可以存取整個项目,重構可以確保项目的每一個地方在重構之後可以繼續運作。
; 跨團隊協作
: 在使用原始相依性套件(從原始代码編譯的相依性套件)的 monorepo 中,團隊可以改善其他團隊正在進行的项目。這樣能讓代码所有人更富有彈性。
限制與缺點
; 損失版本資訊
: 雖然不是必要的,但一些 monorepo 構建在存儲庫中的所有项目中使用同一個版本號。 將會導致損失每個项目的語義版本控制。 要注意的是在某些版本控制系統中,此限制不是問題。 例如,當使用 Subversion 時,可以下載存儲庫的任何部分(甚至是單個目錄),並且可以使用基於路徑的授權來限制對存儲庫某些部分的存取。
; 預設需要更多存儲空間
: 使用分離式存儲庫,在預設的情況下只能接收感興趣的项目。使用 monorepo,在預設情況下您可以取出(check out)所有项目。 這樣將會佔用大量存儲空間。 雖然所有版本都有執行部份取出(partial checkout)的機制 但這樣的做法會破壞 monorepo 的一些優點。
可擴充性的挑戰
擁有大型项目的公司都會遇到了 monorepos 的障礙,特別是與構建工具和版本控制系統有關。 Google的monorepo被認為是世界上最龐大,符合超大規模系統的分類
擴充版本控制软件
使用或改用現有版本控制软件的公司發現,該软件無法有效處理大型 monorepo 所需的資料量。 Facebook 和微軟分別選擇貢獻或對現有的版本控制軟件 Mercurial 和 Git建立分叉版本,而谷歌最終建立了自己的版本控制系統。十多年來,Google 一直依靠託管在單一機器上的 Perforce。 2005 年,Google 的構建伺服器可能一次被鎖定長達 10 分鐘。谷歌在 2010 年將其改進為 30 秒 - 1 分鐘。 因為擴充問題,Google 最終開發自己的內部分散式版本控制系統,稱為 Piper。 並在 2014 年 1 月使該系統比起 Git 中的競爭解決方案更快。
2017 年 5 月,Microsoft 宣布幾乎所有 Windows 工程師都使用 Git monorepo。 在過渡期內,Microsoft 對 Git 客戶端做出了大量的上游貢獻,移除不必要的檔案存取並改善使用 Git 虛擬檔案系統處理大型檔案的能力。
擴充構建软件
很少有構建工具在 monorepo 中有良好表現-
Twitter 於 2011 年開始開發 Pants,因為在當時 Facebook 的 Buck 和谷歌的 Bazel 都是不是開始原始代码的工具。 Twitter 以 Apache 2.0 授權的方式於 2012 年開放 Pants 的源代码。
Please 是一款基於 Go 語言的構建系統,由 Thought Machine 在 2016 年開發,Thought Machine 也是受到 Google 的 Bazel 的啟發,同時也是因為對 Facebook 的 Buck 不滿。
參考文獻
评论 (0)