Monorepo 與 Multi-Repo:代碼存儲庫策略的優缺點

通過 Git 託管和管理代碼有兩種主要策略:monorepo 與 multi-repo。這兩種方法各有優缺點。

嘗試免費演示

我們可以對任何語言的任何代碼庫使用任何一種方法。您可以將這些策略中的任何一個用於包含少量庫到數千個庫的項目。即使涉及幾個團隊成員或數百人,或者您想託管私有或開源代碼,您仍然可以根據各種因素選擇 monorepo 或 multirepo。

每種方法的優點和缺點是什麼?我們什麼時候應該使用其中一個?讓我們一探究竟吧!

什麼是回購?

存儲庫(repository 的縮寫)是項目中所有更改和文件的存儲,使開發人員能夠在整個開發階段對項目資產進行「版本控制」。

我們通常指的是 Git 存儲庫(由 GitHub、GitLab 或 Bitbucket 提供),但該概念也適用於其他版本控制系統(例如 Mercurial)。

monorepo 方法和多 repo 方法。🚀 探索本指南中的每一個 ⬇️點擊推文

什麼是 Monorepo?

monorepo 方法使用單個存儲庫來託管組成公司項目的多個庫或服務的所有代碼。在最極端的情況下,來自一家公司的整個代碼庫——跨越各種項目並用不同的語言編碼——都託管在一個存儲庫中。

Monorepo 的好處

將整個代碼庫託管在單個存儲庫上有以下好處。

降低進入壁壘

當新員工開始為公司工作時,他們需要下載代碼並安裝所需的工具才能開始工作。假設項目分散在許多存儲庫中,每個存儲庫都有其安裝說明和所需的工具。在這種情況下,初始設置將很複雜,而且文檔通常不完整,需要這些新團隊成員向同事尋求幫助。

monorepo 簡化了問題。由於有一個包含所有代碼和文檔的位置,您可以簡化初始設置。

位於中心的代碼管理

擁有一個存儲庫可以讓所有開發人員看到所有代碼。它簡化了代碼管理,因為我們可以使用單個問題跟蹤器來觀察整個應用程序生命周期中的所有問題。

例如,當問題跨越兩個(或更多)子庫且依賴庫上存在錯誤時,這些特徵很有價值。對於多個存儲庫,可能很難找到發生問題的代碼段。

最重要的是,我們需要確定使用哪個存儲庫來創建問題,然後邀請和交叉標記其他團隊的成員來幫助解決問題。

但是,使用 monorepo,定位代碼問題和協作排除故障都變得更容易實現。

無痛的應用範圍重構

在創建代碼的應用程序範圍重構時,多個庫將受到影響。如果您通過多個存儲庫託管它們,管理所有不同的拉取請求以保持它們彼此同步可能是一個挑戰。

monorepo 可以輕鬆地對所有庫的所有代碼執行所有修改,並在單個拉取請求下提交。

更難打破相鄰的功能

使用 monorepo,我們可以為所有庫設置所有測試,以便在修改任何單個庫時運行。因此,在某些庫中進行更改的可能性已最小化對其他庫的不利影響。

團隊共享發展文化

儘管並非不可能,但使用 monorepo 方法,在不同團隊之間激發獨特的亞文化變得具有挑戰性。由於它們將共享相同的存儲庫,因此它們很可能將共享相同的編程和管理方法並使用相同的開發工具。

Monorepo 方法的問題

對我們所有的代碼使用單個存儲庫有幾個缺點。

更慢的開發周期

當庫的代碼包含破壞性更改,導致依賴庫的測試失敗時,還必須在合併更改之前修復代碼。

如果這些庫依賴於其他團隊,他們正忙於處理其他任務並且無法(或不願意)調整他們的代碼以避免破壞性更改並通過測試,則新功能的開發可能會停滯。

更重要的是,該項目很可能僅以公司中最慢團隊的速度開始推進。這種結果可能會使速度最快的團隊成員感到沮喪,為他們想要離開公司創造條件。

此外,庫還需要為所有其他庫運行測試。要運行的測試越多,運行它們所需的時間就越多,從而降低了我們迭代代碼的速度。

需要下載整個代碼庫

當 monorepo 包含公司的所有代碼時,它可能會非常龐大​​,包含數千兆位元組的數據。要為託管在其中的任何庫做出貢獻,任何人都需要下載整個存儲庫。

處理龐大的代碼庫意味著我們硬碟驅動器上的空間使用不當,並且與它的交互速度較慢。例如,執行 git status 或使用正則表達式在代碼庫中搜索等日常操作可能比使用多個 repos 花費的時間多幾秒甚至幾分鐘。

未修改的庫可能是新版本

當我們標記 monorepo 時,其中的所有代碼都被分配了新的標記。如果此操作觸發新版本,則存儲庫中託管的所有庫都將使用標籤中的版本號新發布,即使其中許多庫可能沒有任何更改。

分叉更難

開源項目必須讓貢獻者儘可能容易地參與進來。使用多個存儲庫,貢獻者可以直接前往他們想要貢獻的項目的特定存儲庫。但是,對於託管各種項目的 monorepo,貢獻者必須首先引導他們進入正確的項目,並且需要了解他們的貢獻可能如何影響所有其他項目。

什麼是多回購?

多存儲庫方法使用多個存儲庫來託管公司開發的項目的多個庫或服務。在最極端的情況下,它將在其存儲庫下託管每組最小的可重用代碼或獨立功能(例如微服務)。

多重回購的好處

獨立於所有其他圖書館託管每個圖書館提供了許多好處。

獨立庫版本控制

標記存儲庫時,它的整個代碼庫都被分配了「新」標籤。由於存儲庫中只有特定庫的代碼,因此可以獨立於其他地方託管的所有其他庫對庫進行標記和版本控制。

每個庫都有一個獨立的版本有助於定義應用程序的依賴樹,允許我們配置要使用的每個庫的版本。

獨立服務版本

由於存儲庫僅包含某些服務的代碼而沒有其他任何內容,因此它可以有自己的部署周期,與訪問它的應用程序取得的任何進展無關。

該服務可以使用快速發布周期,例如持續交付(在通過所有測試後部署新代碼)。一些訪問該服務的庫可能使用較慢的發布周期,例如那些每周只發布一次新版本的庫。

幫助定義整個組織的訪問控制

只有參與開發庫的團隊成員需要添加到相應的存儲庫並下載其代碼。因此,應用程序中的每一層都有一個隱式訪問控制策略。與庫相關的人員將被授予編輯許可權,其他人可能無法訪問存儲庫。或者他們可能被授予閱讀權,但沒有編輯權。

允許團隊自主工作

團隊成員可以獨立於所有其他團隊設計庫的架構並實現其代碼。他們可以根據庫在一般上下文中的行為做出決策,而不受來自某些外部團隊或應用程序的特定要求的影響。

訂閱時事通訊

想知道我們是如何將流量增加超過 1000% 的嗎?

加入 20,000 多名其他人的行列,他們會收到我們的每周時事通訊,其中包含 WordPress 內幕技巧!

現在訂閱

多回購方法的問題

使用多個存儲庫可能會引起幾個問題。

庫必須不斷地重新同步

當發布包含重大更改的庫的新版本時,需要調整依賴於該庫的庫以開始使用最新版本。如果庫的發布周期比其依賴庫的發布周期快,它們之間可能很快就會變得不同步。

團隊需要不斷追趕以使用其他團隊的最新版本。鑒於不同的團隊有不同的優先順序,這有時可能難以實現。

因此,無法趕上的團隊最終可能會堅持使用依賴庫的過時版本。這一結果將對應用程序產生影響(在安全性、速度和其他考慮方面),跨庫的開發差距可能只會越來越大。

五月碎片團隊

當不同的團隊不需要互動時,他們可能會在自己的孤島中工作。從長遠來看,這可能會導致團隊在公司內產生他們的亞文化,例如採用不同的編程或管理方法或使用不同的開發工具集。

如果某個團隊成員最終需要在不同的團隊中工作,他們可能會遭受一些文化衝擊並學習一種新的工作方式。

Monorepo 與 Multi-Repo:主要區別

這兩種方法最終都處理相同的目標:管理代碼庫。因此,他們必須解決相同的挑戰,包括發布管理、促進團隊成員之間的協作、處理問題、運行測試等。

他們的主要區別在於他們對團隊成員做出決定的時間安排:無論是前期單回購還是後期多回購。

讓我們更詳細地分析這個想法。

由於所有庫在多存儲庫中都是獨立版本控制的,因此發布具有重大更改的庫的團隊可以通過將新的主要版本號分配給最新版本來安全地進行。其他組可以讓他們的依賴庫堅持舊版本,一旦他們的代碼被改編就切換到新的。

這種方法讓每個負責的團隊決定何時調整所有其他庫,他們可以隨時進行調整。如果他們做得太晚並且發布了新的庫版本,縮小庫之間的差距將變得越來越困難。

因此,雖然一個團隊可以快速且頻繁地迭代他們的代碼,但其他團隊可能無法趕上,最終產生分歧的庫。

另一方面,在 monorepo 環境中,我們不能發布一個庫的新版本來破壞其他庫,因為它們的測試將失敗。在這種情況下,第一個團隊必須與第二個團隊溝通以合併更改。

這種方法迫使團隊在必須對單個庫進行更改時完全適應所有庫。所有團隊都被迫相互交談並共同達成解決方案。

厭倦了沒有答案的低於 1 級的 WordPress 託管支持?試試我們世界一流的支持團隊!查看我們的計劃

結果,第一個團隊將無法像他們希望的那樣快速迭代,但是跨不同庫的代碼永遠不會開始出現分歧。

總而言之,多回購方法可以幫助在團隊之間創造一種「快速行動並打破常規」的文化,在這種文化中,靈活的獨立團隊可以以他們的速度產生他們的輸出。相反,monorepo 方法有利於意識和關懷的文化,團隊不應該被拋在後面獨自處理問題。

混合 Poly-As-Mono 方法

如果我們不能決定是使用多存儲庫還是 monorepo 方法,還有一種中間方法:使用多個存儲庫並使用一些工具來保持它們同步,使其類似於 monorepo 但具有更大的靈活性。

Meta 就是這樣一種工具。它在子目錄下組織多個存儲庫,並提供一個命令行界面,可以同時對所有存儲庫執行相同的命令。

元存儲庫包含有關哪些存儲庫構成項目的信息。通過元克隆這個存儲庫將遞歸地克隆所有需要的存儲庫,使新的團隊成員可以更輕鬆地立即開始他們的項目。

要克隆一個元存儲庫及其所有定義的多個存儲庫,我們必須執行以下操作:

元 git 克隆 [元回購網址]

Meta 將為每個存儲庫執行一個 git clone 並將其放在子文件夾中:

克隆元項目

克隆元項目。(圖片來源:github.com/mateodelnorte/meta)

此後,執行 meta exec 命令將在每個子文件夾上執行該命令。例如,在每個存儲庫上執行 git checkout master 是這樣完成的:

元執行「git checkout master」

混合 Mono-As-Poly 方法

另一種方法是通過用於開發的 monorepo 管理代碼,但將每個庫的代碼複製到其獨立的存儲庫中進行部署。

這種策略在 PHP 生態系統中很普遍,因為 Packagist(主要的 Composer 存儲庫)需要一個公共存儲庫 URL 來發布包,並且不可能指明該包位於存儲庫的子目錄中。

鑒於 Packagist 的限制,PHP 項目仍然可以使用 monorepo 進行開發,但它們必須使用多 repo 方法進行部署。

為了實現這種轉換,我們可以使用 git subtree split 執行腳本或使用執行相同邏輯的可用工具之一:

  • Git 子樹拆分器
  • Git子拆分
  • Monorepo 拆分的 GitHub 操作

誰在使用 Monorepo 和 Multi-Repo

幾家大型科技公司偏愛 monorepo 方法,而其他公司則決定使用 multi-repo 方法。

谷歌、Facebook、Twitter 和 Uber 都公開擔保採用 monorepo 方法。微軟運行著地球上最大的 Git monorepo 來託管 Windows 操作系統的源代碼。

另一方面,Netflix、亞馬遜和 Lyft 是使用多回購方法的著名公司。

在混合 poly-as-mono 方面,Android 更新多個存儲庫,這些存儲庫像 monorepo 一樣進行管理。

在混合 mono-as-poly 方面,Symfony 將其所有組件的代碼保存在一個 monorepo 中。他們將其拆分為獨立的存儲庫進行部署(例如 symfony/dependency-injection 和 symfony/event-dispatcher。)

Monorepo 和 Multi-Repo 的示例

GitHub 上的 WordPress 帳戶託管了 monorepo 和 multi-repo 方法的示例。

WordPress 塊編輯器 Gutenberg 由幾十個 JavaScript 包組成。這些包都託管在 WordPress/gutenberg monorepo 上,並通過 Lerna 進行管理,以幫助將它們發布到 npm 存儲庫中。

Openverse 是開放許可媒體的搜索引擎,其主要部分託管在獨立的存儲庫中:前端、目錄和 API。

Monorepo vs Multi-Repo:如何選擇?

對於許多開發問題,對於應該使用哪種方法沒有預定義的答案。不同的公司和項目將根據其獨特的條件從一種或另一種策略中受益,例如:

  • 代碼庫有多大?它是否包含千兆位元組的數據?
  • 有多少人會在代碼庫上工作?大約是 10、100 還是 1,000?
  • 會有多少個包裹?大約是 10、100 還是 1,000?
  • 團隊在給定時間需要處理多少個包?
  • 包的耦合度如何?
  • 是否涉及不同的編程語言?它們是否需要安裝特定的軟體或特殊的硬體才能運行?
  • 需要多少部署工具,設置起來有多複雜?
  • 公司的文化是什麼?是否鼓勵團隊合作?
  • 團隊知道如何使用哪些工具和技術?

您應該為代碼庫採用哪種方法?🤔 在這裡了解更多👇點擊推文

概括

託管和管理代碼有兩種主要策略:monorepo 與 multi-repo。monorepo 方法需要將不同庫或項目的代碼 – 甚至來自公司的所有代碼 – 存儲在單個存儲庫中。並且多存儲庫系統將代碼劃分為單元,例如庫或服務,並將它們的代碼託管在獨立的存儲庫中。

使用哪種方法取決於多種條件。這兩種策略都有幾個優點和缺點,我們剛剛在本文中詳細介紹了所有這些。

您對 monorepos 或 multi-repos 有任何疑問嗎?請在評價部分留下您的意見!

通過以下方式節省時間、成本並最大限度地提高站點性能:

  • 來自 WordPress 託管專家的即時幫助,24/7。
  • Cloudflare 企業集成。
  • 全球受眾覆蓋全球 28 個數據中心。
  • 使用我們內置的應用程序性能監控進行優化。

所有這些以及更多,都在一個沒有長期合同、協助遷移和 30 天退款保證的計劃中。查看我們的計劃或與銷售人員交談以找到適合您的計劃。

相關文章