Có hai chiến lược chính để lưu trữ và quản lý mã thông qua Git: monorepo và multi-repo. Cả hai cách tiếp cận đều có ưu và nhược điểm của chúng.

Chúng tôi có thể sử dụng một trong hai cách tiếp cận cho bất kỳ cơ sở mã bằng bất kỳ ngôn ngữ nào. Bạn có thể sử dụng bất kỳ chiến lược nào trong số các chiến lược này cho các dự án chứa một số ít thư viện đến hàng nghìn thư viện trong số đó. Ngay cả khi nó liên quan đến một vài hoặc hàng trăm thành viên trong nhóm, hoặc bạn muốn lưu trữ mã nguồn mở hoặc riêng tư, bạn vẫn có thể sử dụng monorepo hoặc multi-repo dựa trên các yếu tố khác nhau.

Những lợi ích và hạn chế của mỗi cách tiếp cận là gì? Khi nào chúng ta nên sử dụng cái này hay cái kia? Hãy cùng tìm hiểu!

Repos là gì?

Kho lưu trữ (viết tắt của repository) là nơi lưu trữ tất cả các thay đổi và tệp từ một dự án, cho phép các nhà phát triển “kiểm soát phiên bản” các tài sản của dự án trong suốt giai đoạn phát triển của nó.

Chúng tôi thường đề cập đến kho lưu trữ Git (do GitHub, GitLab hoặc Bitbucket cung cấp), nhưng khái niệm này cũng áp dụng cho các hệ thống kiểm soát phiên bản khác (chẳng hạn như Mercurial).

Monorepo là gì?

Phương pháp monorepo sử dụng một kho lưu trữ duy nhất để lưu trữ tất cả mã cho nhiều thư viện hoặc dịch vụ tạo ra các dự án của công ty. Ở mức cực đoan nhất, toàn bộ codebase từ một công ty – bao gồm nhiều dự án khác nhau và được mã hóa bằng các ngôn ngữ khác nhau – được lưu trữ trong một kho lưu trữ duy nhất.

Lợi ích của Monorepo

Lưu trữ toàn bộ cơ sở mã trên một kho lưu trữ duy nhất mang lại những lợi ích sau.

Giảm rào cản gia nhập

Khi nhân viên mới bắt đầu làm việc cho một công ty, họ cần tải xuống mã và cài đặt các công cụ cần thiết để bắt đầu thực hiện nhiệm vụ của mình. Giả sử dự án nằm rải rác trên nhiều kho, mỗi kho đều có hướng dẫn cài đặt và công cụ cần thiết. Trong trường hợp đó, quá trình thiết lập ban đầu sẽ phức tạp và thường xuyên là tài liệu sẽ không đầy đủ, yêu cầu các thành viên mới trong nhóm này liên hệ với đồng nghiệp để được trợ giúp.

Một monorepo đơn giản hóa vấn đề. Vì có một vị trí duy nhất chứa tất cả mã và tài liệu, bạn có thể hợp lý hóa thiết lập ban đầu.

Quản lý mã nằm ở trung tâm

Có một kho lưu trữ duy nhất cung cấp khả năng hiển thị của tất cả mã cho tất cả các nhà phát triển. Nó đơn giản hóa việc quản lý mã vì chúng tôi có thể sử dụng một trình theo dõi vấn đề duy nhất để xem tất cả các vấn đề trong suốt vòng đời của ứng dụng.

Ví dụ: những đặc điểm này có giá trị khi một sự cố kéo dài hai (hoặc nhiều) thư viện con với lỗi tồn tại trên thư viện phụ thuộc. Với nhiều kho lưu trữ, có thể khó khăn để tìm ra đoạn mã nơi sự cố xảy ra.

Trên hết, chúng tôi cần phải tìm ra kho lưu trữ nào sẽ sử dụng để tạo ra vấn đề và sau đó mời và gắn thẻ chéo các thành viên của các nhóm khác để giúp giải quyết vấn đề.

Tuy nhiên, với monorepo, cả việc xác định sự cố mã và cộng tác để khắc phục sự cố đều trở nên đơn giản hơn.

Tái cấu trúc toàn bộ ứng dụng không đau

Khi tạo bản tái cấu trúc mã trên toàn ứng dụng, nhiều thư viện sẽ bị ảnh hưởng. Nếu bạn đang lưu trữ chúng qua nhiều kho lưu trữ, việc quản lý tất cả các yêu cầu kéo khác nhau để giữ chúng được đồng bộ hóa với nhau có thể là một thách thức.

Một monorepo giúp bạn dễ dàng thực hiện tất cả các sửa đổi đối với tất cả mã cho tất cả các thư viện và gửi nó theo một yêu cầu kéo duy nhất.

Khó phá vỡ chức năng liền kề hơn

Với monorepo, chúng tôi có thể thiết lập tất cả các bài kiểm tra cho tất cả các thư viện để chạy bất cứ khi nào bất kỳ thư viện đơn lẻ nào được sửa đổi. Do đó, khả năng thực hiện thay đổi ở một số thư viện đã giảm thiểu tác động xấu đến các thư viện khác.

Các đội Chia sẻ Văn hóa Phát triển

Mặc dù không phải là không thể, nhưng với cách tiếp cận monorepo, việc truyền cảm hứng cho các nền văn hóa phụ độc đáo giữa các đội khác nhau sẽ trở nên khó khăn. Vì họ sẽ chia sẻ cùng một kho lưu trữ nên rất có thể họ sẽ chia sẻ cùng một phương pháp lập trình và quản lý cũng như sử dụng các công cụ phát triển giống nhau.

Các vấn đề với Phương pháp Monorepo

Sử dụng một kho lưu trữ duy nhất cho tất cả mã của chúng tôi có một số hạn chế.

Chu kỳ phát triển chậm hơn

Khi mã cho thư viện chứa các thay đổi vi phạm, làm cho việc kiểm tra các thư viện phụ thuộc không thành công, thì mã cũng phải được sửa trước khi hợp nhất các thay đổi.

Nếu các thư viện này phụ thuộc vào các nhóm khác, những người đang bận thực hiện một số nhiệm vụ khác và không thể (hoặc sẵn sàng) điều chỉnh mã của họ để tránh các thay đổi vi phạm và đã vượt qua các bài kiểm tra, thì việc phát triển tính năng mới có thể bị đình trệ.

Hơn nữa, dự án có thể bắt đầu tiến triển chỉ với tốc độ của nhóm chậm nhất trong công ty. Kết cục này có thể khiến thành viên của những đội nhanh nhất nản lòng, tạo điều kiện cho họ muốn rời bỏ công ty.

Ngoài ra, một thư viện cũng sẽ cần chạy các bài kiểm tra cho tất cả các thư viện khác. Càng chạy nhiều thử nghiệm, càng mất nhiều thời gian để chạy chúng, làm chậm tốc độ chúng ta có thể lặp lại trên mã của mình.

Yêu cầu tải xuống toàn bộ cơ sở mã

Khi monorepo chứa tất cả mã cho một công ty, nó có thể rất lớn, chứa hàng gigabyte dữ liệu. Để đóng góp cho bất kỳ thư viện nào được lưu trữ bên trong, bất kỳ ai cũng sẽ yêu cầu tải xuống toàn bộ kho lưu trữ.

Xử lý cơ sở mã rộng lớn ngụ ý sử dụng ít dung lượng trên ổ cứng của chúng ta và tương tác với nó chậm hơn. Ví dụ: các hành động hàng ngày như thực hiện git status hoặc tìm kiếm trong codebase với regex có thể mất nhiều giây hoặc thậm chí vài phút so với thực hiện với nhiều repo.

Thư viện chưa sửa đổi có thể được tạo phiên bản mới

Khi chúng tôi gắn thẻ monorepo, tất cả mã bên trong sẽ được gán thẻ mới. Nếu hành động này kích hoạt bản phát hành mới, thì tất cả các thư viện được lưu trữ trong kho lưu trữ sẽ được phát hành mới với số phiên bản từ thẻ, mặc dù nhiều thư viện trong số đó có thể không có bất kỳ thay đổi nào.

Forking khó hơn

Các dự án mã nguồn mở phải giúp những người đóng góp tham gia dễ dàng nhất có thể. Với nhiều kho lưu trữ, những người đóng góp có thể trực tiếp đến kho lưu trữ cụ thể cho dự án mà họ muốn đóng góp. Tuy nhiên, với một monorepo lưu trữ các dự án khác nhau, những người đóng góp trước tiên phải điều hướng theo cách của họ vào dự án phù hợp và sẽ cần hiểu đóng góp của họ có thể ảnh hưởng như thế nào đến tất cả các dự án khác.

Multi-Repo là gì?

Phương pháp đa kho lưu trữ sử dụng một số kho lưu trữ để lưu trữ nhiều thư viện hoặc dịch vụ của một dự án do một công ty phát triển. Ở mức cao nhất, nó sẽ lưu trữ mọi bộ mã tối thiểu có thể tái sử dụng hoặc chức năng độc lập (chẳng hạn như một microservice) trong kho lưu trữ của nó.

Lợi ích của Multi-Repo

Lưu trữ mọi thư viện độc lập với tất cả các thư viện khác mang lại rất nhiều lợi ích.

Phiên bản Thư viện Độc lập

Khi gắn thẻ kho lưu trữ, toàn bộ cơ sở mã của nó được gán thẻ “mới”. Vì chỉ có mã cho một thư viện cụ thể mới có trên kho lưu trữ, nên thư viện có thể được gắn thẻ và tạo phiên bản độc lập với tất cả các thư viện khác được lưu trữ ở nơi khác.

Có một phiên bản độc lập cho mọi thư viện giúp xác định cây phụ thuộc cho ứng dụng, cho phép chúng tôi định cấu hình phiên bản nào của từng thư viện để sử dụng.

Bản phát hành dịch vụ độc lập

Vì kho lưu trữ chỉ chứa mã cho một số dịch vụ và không có gì khác, nên nó có thể có chu kỳ triển khai riêng, độc lập với bất kỳ tiến trình nào được thực hiện trên các ứng dụng truy cập nó.

Dịch vụ có thể sử dụng chu kỳ phát hành nhanh như phân phối liên tục (nơi mã mới được triển khai sau khi nó vượt qua tất cả các bài kiểm tra). Một số thư viện truy cập dịch vụ có thể sử dụng chu kỳ phát hành chậm hơn, chẳng hạn như những thư viện chỉ tạo bản phát hành mới mỗi tuần một lần.

Giúp xác định quyền kiểm soát truy cập trong toàn tổ chức

Chỉ những thành viên trong nhóm tham gia phát triển thư viện mới cần được thêm vào kho lưu trữ tương ứng và tải xuống mã của nó. Do đó, có một chiến lược kiểm soát truy cập ngầm cho mỗi lớp trong ứng dụng. Những người liên quan đến thư viện sẽ được cấp quyền chỉnh sửa và những người khác có thể không có quyền truy cập vào kho lưu trữ. Hoặc họ có thể được trao quyền đọc nhưng không có quyền chỉnh sửa.

Đăng kí để nhận thư mới

Cho phép các nhóm làm việc một cách tự chủ

Các thành viên trong nhóm có thể thiết kế kiến trúc của thư viện và triển khai mã của nó hoạt động tách biệt với tất cả các nhóm khác. Họ có thể đưa ra quyết định dựa trên những gì thư viện thực hiện trong bối cảnh chung mà không bị ảnh hưởng bởi các yêu cầu cụ thể từ một số nhóm hoặc ứng dụng bên ngoài.

Các vấn đề với Phương pháp Tiếp cận Nhiều Repo

Sử dụng nhiều kho lưu trữ có thể làm phát sinh một số vấn đề.

Các thư viện phải liên tục được đồng bộ hóa lại

Khi phiên bản mới của thư viện chứa các thay đổi đột phá được phát hành, các thư viện tùy thuộc vào thư viện này sẽ cần được điều chỉnh để bắt đầu sử dụng phiên bản mới nhất. Nếu chu kỳ phát hành của thư viện nhanh hơn chu kỳ phát hành của các thư viện phụ thuộc, chúng có thể nhanh chóng trở nên không đồng bộ với nhau.

Các đội sẽ cần phải liên tục cập nhật để sử dụng các bản phát hành mới nhất từ các đội khác. Do các đội khác nhau có những ưu tiên khác nhau, điều này đôi khi có thể khó đạt được.

Do đó, một nhóm không bắt kịp có thể dính vào phiên bản lỗi thời của thư viện phụ thuộc vào. Kết quả này sẽ có ý nghĩa đối với ứng dụng (về bảo mật, tốc độ và các cân nhắc khác) và khoảng cách phát triển giữa các thư viện có thể chỉ ngày càng rộng hơn.

Nhóm có thể phân mảnh

Khi các đội khác nhau không cần tương tác, họ có thể làm việc trong hầm chứa của riêng mình. Về lâu dài, điều này có thể dẫn đến việc các nhóm sản xuất văn hóa con của họ trong công ty, chẳng hạn như sử dụng các phương pháp lập trình hoặc quản lý khác nhau hoặc sử dụng các bộ công cụ phát triển khác nhau.

Nếu một số thành viên trong nhóm cuối cùng cần làm việc trong một nhóm khác, họ có thể bị sốc văn hóa và học một cách mới để thực hiện công việc của mình.

Monorepo so với Multi-Repo: Sự khác biệt chính

Cả hai cách tiếp cận cuối cùng đều giải quyết cùng một mục tiêu: quản lý cơ sở mã. Do đó, cả hai đều phải giải quyết những thách thức giống nhau, bao gồm quản lý phát hành, thúc đẩy sự hợp tác giữa các thành viên trong nhóm, xử lý các vấn đề, chạy thử nghiệm và những thứ khác.

Sự khác biệt chính của họ liên quan đến thời gian của họ để các thành viên trong nhóm đưa ra quyết định: trả trước cho monorepo hoặc xuống dòng cho nhiều repo.

Hãy phân tích ý tưởng này chi tiết hơn.

Bởi vì tất cả các thư viện được tạo phiên bản độc lập trong multi-repo, một nhóm phát hành thư viện có các thay đổi vi phạm có thể thực hiện điều đó một cách an toàn bằng cách gán một số phiên bản chính mới cho bản phát hành mới nhất. Các nhóm khác có thể yêu cầu các thư viện phụ thuộc của họ bám vào phiên bản cũ và chuyển sang phiên bản mới sau khi mã của họ đã được điều chỉnh.

Cách tiếp cận này đưa ra quyết định về thời điểm thích ứng tất cả các thư viện khác cho từng nhóm chịu trách nhiệm, những người có thể thực hiện bất kỳ lúc nào. Nếu họ làm điều đó quá muộn và các phiên bản thư viện mới được phát hành, việc thu hẹp khoảng cách giữa các thư viện sẽ ngày càng trở nên khó khăn.

Do đó, trong khi một nhóm có thể lặp lại nhanh chóng và thường xuyên trên mã của họ, các nhóm khác có thể không thể bắt kịp, cuối cùng tạo ra các thư viện khác nhau.

Mặt khác, trong môi trường monorepo, chúng tôi không thể phát hành phiên bản mới của một thư viện mà phá vỡ một số thư viện khác vì các thử nghiệm của chúng sẽ không thành công. Trong trường hợp này, đội đầu tiên phải giao tiếp với đội thứ hai để kết hợp các thay đổi.

Bạn cảm thấy mệt mỏi với việc hỗ trợ lưu trữ WordPress cấp độ 1 phụ mà không có câu trả lời? Hãy thử nhóm hỗ trợ đẳng cấp thế giới của chúng tôi! Kiểm tra các kế hoạch của chúng tôi

Cách tiếp cận này buộc các nhóm phải điều chỉnh hoàn toàn tất cả các thư viện bất cứ khi nào có sự thay đổi đối với một thư viện. Tất cả các đội buộc phải nói chuyện với nhau và cùng nhau đạt được giải pháp.

Kết quả là, nhóm đầu tiên sẽ không thể lặp lại nhanh như họ muốn, nhưng mã trên các thư viện khác nhau sẽ không bắt đầu phân kỳ.

Tóm lại, cách tiếp cận multi-repo có thể giúp tạo ra văn hóa “di chuyển nhanh và phá vỡ mọi thứ” giữa các nhóm, nơi các nhóm độc lập nhanh nhẹn có thể tạo ra kết quả đầu ra với tốc độ của họ. Thay vào đó, phương pháp monorepo ủng hộ một nền văn hóa nhận thức và quan tâm, nơi các nhóm không nên bị bỏ lại phía sau để tự mình giải quyết một vấn đề.

Phương pháp tiếp cận hỗn hợp Poly-As-Mono

Nếu chúng ta không thể quyết định sử dụng phương pháp multi-repo hay monorepo, thì cũng có cách tiếp cận ở giữa: sử dụng nhiều repo và sử dụng một số công cụ để giữ cho chúng được đồng bộ hóa, làm cho nó giống như một monorepo nhưng linh hoạt hơn.

Meta là một trong những công cụ như vậy. Nó tổ chức nhiều kho lưu trữ dưới các thư mục con và cung cấp một giao diện dòng lệnh thực thi cùng một lệnh trên tất cả chúng đồng thời.

Một kho lưu trữ meta chứa thông tin mà các kho lưu trữ tạo nên một dự án. Nhân bản kho lưu trữ này thông qua meta sau đó sẽ sao chép đệ quy tất cả các kho lưu trữ được yêu cầu, giúp các thành viên mới trong nhóm dễ dàng bắt đầu làm việc với dự án của họ ngay lập tức.

Để sao chép một kho lưu trữ meta và tất cả các kho lưu trữ đã xác định của nó, chúng ta phải thực hiện như sau:

meta git clone [meta repo url]

Meta sẽ thực thi một git clone cho mỗi kho lưu trữ và đặt nó vào một thư mục con:

Cloning a meta project
Nhân bản một siêu dự án. (Nguồn ảnh: github.com/mateodelnorte/meta)

Từ đó, thực hiện lệnh meta exec execute sẽ thực hiện lệnh trên từng thư mục con. Ví dụ: thực thi git checkout master trên mỗi kho lưu trữ được thực hiện như sau:

meta exec "git checkout master"

Phương pháp tiếp cận Mono-As-Poly kết hợp

Một cách tiếp cận khác là quản lý mã thông qua một monorepo để phát triển, nhưng sao chép mã của mỗi thư viện vào kho lưu trữ độc lập của nó để triển khai.

Chiến lược này phổ biến trong hệ sinh thái PHP vì Packagist (kho lưu trữ của Nhà soạn nhạc chính) yêu cầu URL của kho lưu trữ công khai để xuất bản một gói và không thể chỉ ra rằng gói đó nằm trong một thư mục con của kho lưu trữ.

Với giới hạn của Packagist, các dự án PHP vẫn có thể sử dụng monorepo để phát triển, nhưng chúng phải sử dụng cách tiếp cận multi-repo để triển khai.

Để đạt được chuyển đổi này, chúng tôi có thể thực thi một tập lệnh với git subtree split Hoặc sử dụng một trong các công cụ có sẵn thực hiện cùng một logic:

  • Git Subtree Splitter
  • Git Subsplit
  • GitHub Action cho Monorepo Split

Ai đang sử dụng Monorepo so với Multi-Repo

Một số công ty công nghệ lớn ưa chuộng phương pháp monorepo, trong khi những công ty khác đã quyết định sử dụng phương pháp multi-repo.

Google, Facebook, Twitter và Uber đều đã công khai xác nhận về phương pháp monorepo. Microsoft chạy monorepo Git lớn nhất hành tinh để lưu trữ mã nguồn của hệ điều hành Windows.

Ở phía đối diện, Netflix, Amazon và Lyft là những công ty nổi tiếng sử dụng phương pháp multi-repo.

Về mặt kết hợp poly-as-mono, Android cập nhật nhiều kho lưu trữ, được quản lý giống như một monorepo.

Về mặt hybrid mono-as-poly, Symfony giữ mã cho tất cả các thành phần của nó trong một monorepo. Họ chia nó thành các kho lưu trữ độc lập để triển khai (chẳng hạn như symfony/dependency-injectionsymfony/event-dispatcher .)

Ví dụ về Monorepo và Multi-Repo

Tài khoản WordPress trên GitHub lưu trữ các ví dụ về cả phương pháp monorepo và multi-repo.

Gutenberg, trình chỉnh sửa khối WordPress, bao gồm hàng chục gói JavaScript. Các gói này đều được lưu trữ trên WordPress/gutenberg gutenberg monorepo và được quản lý thông qua Lerna để giúp xuất bản chúng trong kho lưu trữ npm.

Openverse, công cụ tìm kiếm cho các phương tiện được cấp phép công khai, lưu trữ các bộ phận chính của nó trong các kho lưu trữ độc lập: Front-end, Catalog và API.

Monorepo và Multi-Repo: Làm thế nào để chọn?

Như với nhiều vấn đề phát triển, không có câu trả lời được xác định trước về cách tiếp cận mà bạn nên sử dụng. Các công ty và dự án khác nhau sẽ được hưởng lợi từ chiến lược này hay chiến lược khác dựa trên các điều kiện riêng của họ, chẳng hạn như:

  • Cơ sở mã lớn như thế nào? Nó có chứa gigabyte dữ liệu không?
  • Có bao nhiêu người sẽ làm việc trên codebase? Có phải là khoảng 10, 100 hay 1.000?
  • Sẽ có bao nhiêu gói? Có phải là khoảng 10, 100 hay 1.000?
  • Nhóm cần làm bao nhiêu gói tại một thời điểm nhất định?
  • Các gói được liên kết chặt chẽ như thế nào?
  • Các ngôn ngữ lập trình khác nhau có liên quan không? Họ yêu cầu một phần mềm cụ thể được cài đặt hoặc phần cứng đặc biệt để chạy?
  • Có bao nhiêu công cụ triển khai được yêu cầu và mức độ phức tạp để thiết lập chúng?
  • Văn hóa trong công ty là gì? Các nhóm có được khuyến khích cộng tác không?
  • Những công cụ và công nghệ nào mà các nhóm biết cách sử dụng?

Bản tóm tắt

Có hai chiến lược chính để lưu trữ và quản lý mã: monorepo và multi-repo. Phương pháp monorepo đòi hỏi phải lưu trữ mã cho các thư viện hoặc dự án khác nhau – và thậm chí tất cả mã từ một công ty – trong một kho lưu trữ duy nhất. Và hệ thống nhiều kho chia mã thành các đơn vị, chẳng hạn như thư viện hoặc dịch vụ và giữ mã của chúng được lưu trữ trong các kho lưu trữ độc lập.

Việc sử dụng cách tiếp cận nào phụ thuộc vào vô số điều kiện. Cả hai chiến lược đều có một số ưu điểm và nhược điểm, và chúng tôi vừa trình bày chi tiết tất cả chúng trong bài viết này.

Bạn còn câu hỏi nào về monorepos hoặc multi-repos không? Cho chúng tôi biết trong phần ý kiến!


Tiết kiệm thời gian, chi phí và tối đa hóa hiệu suất trang web với:

  • Trợ giúp tức thì từ các chuyên gia lưu trữ WordPress, 24/7.
  • Tích hợp Cloudflare Enterprise.
  • Tiếp cận khán giả toàn cầu với 34 trung tâm dữ liệu trên toàn thế giới.
  • Tối ưu hóa với Giám sát Hiệu suất Ứng dụng được tích hợp sẵn của chúng tôi.

Tất cả những điều đó và hơn thế nữa, trong một kế hoạch không có hợp đồng dài hạn, hỗ trợ di chuyển và đảm bảo hoàn tiền trong 30 ngày. Kiểm tra các kế hoạch của chúng tôi hoặc nói chuyện với bộ phận bán hàng để tìm ra kế hoạch phù hợp với bạn.