Monorepo

在版本控制系統中，Monorepo（“mono”意為“單一”，“repo”是“存儲庫”的縮寫）是一種軟體開發策略，其中多個專案的程式碼存儲在同一個存儲庫裡面。 這種做法至少可以回溯到 2000 年代初期，當時這種做法通常被稱為共享程式碼庫。 Google, Meta, Microsoft, Uber, Airbnb, 以及Twitter 所有這些公司都採用非常大的單一儲存庫（Monorepo），採用不同的策略來擴充具有大量程式碼和日常改版的建置系統和版本控制軟體。

一個相關的概念是龐大應用程式，但是龐大應用程式將其子專案組合成一個大專案，而單一存儲庫（Monorepo）可能包含多個獨立專案。

優點 

與個體存儲庫相比，單一存儲庫有許多潛在優勢：

 方便重複利用程式碼
 類似的功能或溝通協定可以抽像到共享工具庫中並直接包含在專案中，而不需要依靠套件管理器。
 簡化相依性套件管理
 在多個專案依賴於第三方相依性套件的多存儲庫環境中，該相依性套件可能會被多次下載或構建。在 monorepo 中，可以輕鬆優化構建，因為所引用的相依性套件都儲存於同一程式碼庫中。
 原子化提交（Atomic commit）
 當一起運作的專案包含在單獨的存儲庫中時，發布需要同步一個專案的哪些版本與另一個專案一起運作。在相當龐大的專案中，管理相依套性件之間的相容版本可能會變成相依套件地獄（Dependencies hell）。在 monorepo 中，這個問題可以被解決，因為開發者可以原子化的方式修改多個專案。
 大規模程式碼重構
 由於開發者可以存取整個專案，重構可以確保專案的每一個地方在重構之後可以繼續運作。
 跨團隊協作
 在使用原始相依性套件（從原始程式碼編譯的相依性套件）的 monorepo 中，團隊可以改善其他團隊正在進行的專案。這樣能讓程式碼所有人更富有彈性。

限制與缺點 

 損失版本資訊
 雖然不是必要的，但一些 monorepo 構建在存儲庫中的所有專案中使用同一個版本號。 將會導致損失每個專案的語義版本控制。
 缺乏每個專案的存取控制
 使用分離式存儲庫，可以根據需要授予對存儲庫的存取權限。 monorepo 可以對項目中的所有軟體進行讀取，可能會帶來新的安全問題。 要注意的是在某些版本控制系統中，此限制不是問題。 例如，當使用 Subversion 時，可以下載存儲庫的任何部分（甚至是單個目錄），並且可以使用基於路徑的授權來限制對存儲庫某些部分的存取。
 預設需要更多存儲空間
 使用分離式存儲庫，在預設的情況下只能接收感興趣的專案。使用 monorepo，在預設情況下您可以取出（check out）所有專案。 這樣將會佔用大量存儲空間。 雖然所有版本都有執行部份取出（partial checkout）的機制 但這樣的做法會破壞 monorepo 的一些優點。

可擴充性的挑戰 

擁有大型專案的公司都會遇到了 monorepos 的障礙，特別是與構建工具和版本控制系統有關。 Google的monorepo被認為是世界上最龐大，符合超大規模系統的分類 ，每天必須在超過 80 TB 的存儲庫中處理數萬個貢獻提交。

擴充版本控制軟體 

使用或改用現有版本控制軟體的公司發現，該軟體無法有效處理大型 monorepo 所需的資料量。 Facebook 和微軟分別選擇貢獻或對現有的版本控制軟件 Mercurial 和 Git建立分叉版本，而谷歌最終建立了自己的版本控制系統。十多年來，Google 一直依靠託管在單一機器上的 Perforce。 2005 年，Google 的構建伺服器可能一次被鎖定長達 10 分鐘。谷歌在 2010 年將其改進為 30 秒 - 1 分鐘。 因為擴充問題，Google 最終開發自己的內部分散式版本控制系統，稱為 Piper。

Facebook 遇到了版本控制系統 Mercurial 的性能問題，並為客戶端做出了上游貢獻， 並在 2014 年 1 月使該系統比起 Git 中的競爭解決方案更快。

2017 年 5 月，Microsoft 宣布幾乎所有 Windows 工程師都使用 Git monorepo。 在過渡期內，Microsoft 對 Git 客戶端做出了大量的上游貢獻，移除不必要的檔案存取並改善使用 Git 虛擬檔案系統處理大型檔案的能力。

擴充構建軟體 

很少有構建工具在 monorepo 中有良好表現-，並且在存入時執行整個存儲庫的構建和持續整合測試的流程會導致的性能問題。 有定向式圖型構建 Buck、Bazel、Pants 和 Please 等系統，通過將構建和測試劃分到活躍的開發區域來解決這個問題。

Twitter 於 2011 年開始開發 Pants，因為在當時 Facebook 的 Buck 和谷歌的 Bazel 都是不是開始原始程式碼的工具。 Twitter 以 Apache 2.0 授權的方式於 2012 年開放 Pants 的原始程式碼。

Please 是一款基於 Go 語言的構建系統，由 Thought Machine 在 2016 年開發，Thought Machine 也是受到 Google 的 Bazel 的啟發，同時也是因為對 Facebook 的 Buck 不滿。

參考文獻 

版本控制
软件开发