Saat codebase berkembang, banyak perusahaan menghadapi pilihan: apakah menyimpan setiap project di repository terpisah (polyrepo), atau menyatukan semuanya dalam satu repository besar (monorepo)?
Monorepo adalah strategi di mana beberapa aplikasi, library, atau microservices disimpan dalam satu repository Git. Strategi ini dipakai oleh perusahaan besar seperti Google, Facebook, dan Microsoft karena memberikan code sharing, atomic commits, dan single source of truth.
Artikel ini membahas strategi mengelola monorepo dengan Git, tools yang dibutuhkan, dan best practices-nya.
Apa itu Monorepo?
Monorepo = Monolithic Repository — satu repository yang berisi banyak project.
Contoh struktur monorepo:
my-company/
├── packages/
│ ├── ui-components/ # Shared UI library
│ ├── utils/ # Shared utilities
│ └── api-client/ # API client library
├── apps/
│ ├── web/ # Frontend web app
│ ├── mobile/ # Mobile app
│ └── admin/ # Admin dashboard
└── services/
├── auth-service/ # Auth microservice
├── payment-service/ # Payment microservice
└── notification/ # Notification service
Manfaat:
- ✅ Atomic commits: Perubahan di library langsung sync dengan apps
- ✅ Code sharing: Tidak perlu publish/install package setiap kali update
- ✅ Single source of truth: Semua kode di satu tempat
- ✅ Easier refactoring: Rename function di library langsung update semua consumer
Tantangan:
- ❌ Repo size besar: Clone dan fetch lambat
- ❌ Build time lama: Harus selective build hanya yang berubah
- ❌ CI/CD complex: Harus detect perubahan dan test yang relevan
- ❌ Access control sulit: Git tidak support per-folder permissions
Monorepo vs Polyrepo
| Aspek | Monorepo | Polyrepo |
|---|---|---|
| Structure | Semua project dalam 1 repo | Setiap project punya repo sendiri |
| Dependency | Langsung import dari folder lain | Via package manager (npm, pip, maven) |
| Versioning | Satu version untuk semua | Setiap project punya version sendiri |
| CI/CD | Complex, butuh smart build | Simple, per-repo CI/CD |
| Refactoring | Mudah, atomic changes | Sulit, harus coordinate antar repo |
Kapan pakai Monorepo?
- Banyak project yang saling depend
- Tim ingin tight integration dan fast iteration
- Perusahaan besar dengan banyak microservices
Kapan pakai Polyrepo?
- Project independent satu sama lain
- Tim berbeda dengan ownership jelas
- Butuh strict versioning per project
Strategi Git untuk Monorepo
1. Shallow Clone untuk Mempercepat Clone
Monorepo biasanya punya histori commit yang panjang. Gunakan shallow clone untuk clone hanya commit terbaru:
git clone --depth 1 https://github.com/company/monorepo.git
Benefit:
- Clone jauh lebih cepat
- Mengurangi disk space
Tradeoff:
- Tidak bisa lihat histori lama
- Tidak bisa checkout commit lama
2. Sparse Checkout untuk Clone Partial
Sparse checkout memungkinkan kamu clone hanya folder yang dibutuhkan:
git clone --filter=blob:none --sparse https://github.com/company/monorepo.git
cd monorepo
git sparse-checkout init --cone
git sparse-checkout set apps/web packages/ui-components
Hasil:
Hanya folder apps/web dan packages/ui-components yang di-checkout, folder lain diabaikan.
Benefit:
- Clone lebih cepat
- Disk space lebih kecil
- Fokus hanya pada project yang dikerjakan
3. Git Worktrees untuk Multiple Working Directory
Git Worktrees memungkinkan kamu punya beberapa working directory dari satu repository.
Use case: Bekerja di dua branch berbeda tanpa stash/commit.
git worktree add ../monorepo-feature feature-branch
Kamu sekarang punya dua folder:
monorepo/(branchmain)monorepo-feature/(branchfeature-branch)
Kedua folder share satu .git, jadi tidak perlu clone dua kali.
Manfaat:
- Tidak perlu switch branch terus-menerus
- Bisa test feature di satu window, fix bug di window lain
- Build tools berjalan parallel tanpa conflict
4. Use CODEOWNERS untuk Access Control
File .github/CODEOWNERS memungkinkan kamu set ownership per folder:
# CODEOWNERS
/apps/web/ @frontend-team
/services/auth-service/ @backend-team
/packages/ui-components/ @design-system-team
Benefit:
- Pull request otomatis assign reviewer berdasarkan file yang diubah
- Enforce approval dari owner sebelum merge
5. Git Hooks untuk Enforce Quality
Gunakan pre-commit hooks untuk run linter/formatter hanya pada file yang berubah:
Install Husky:
npm install --save-dev husky lint-staged
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"
Configure lint-staged di package.json:
{
"lint-staged": {
"apps/**/*.{js,jsx,ts,tsx}": "eslint --fix",
"packages/**/*.{js,jsx,ts,tsx}": "prettier --write"
}
}
Benefit:
- Hanya run linter pada file yang berubah (cepat)
- Enforce code quality sebelum commit
Tools untuk Mengelola Monorepo
1. Turborepo (Recommended)
Turborepo adalah build system untuk monorepo yang cache hasil build dan run tasks secara parallel.
Install:
npm install turbo --global
File turbo.json:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"]
}
}
}
Run build:
turbo run build
Benefit:
- Caching: Tidak rebuild project yang tidak berubah
- Parallel execution: Build multiple packages sekaligus
- Smart scheduling: Run tasks dalam urutan yang benar
2. Nx (Full-Featured)
Nx adalah full-featured monorepo tool dengan code generation, dependency graph, dan cloud caching.
Install:
npx create-nx-workspace my-monorepo
Generate new app:
nx generate @nrwl/react:app my-app
Build:
nx build my-app
Benefit:
- Dependency graph visualization: Lihat hubungan antar project
- Affected commands: Hanya test/build project yang berubah
- Code generators: Scaffold new apps/libraries dengan konsisten
3. Lerna (Legacy, but Still Used)
Lerna adalah tool lama untuk managing JavaScript monorepos.
Install:
npm install --global lerna
lerna init
Add packages:
lerna create package-name
Publish semua packages:
lerna publish
Note: Lerna kurang aktif dikembangkan. Untuk project baru, gunakan Turborepo atau Nx.
4. Bazel (Google-Style)
Bazel adalah build tool yang dipakai Google untuk monorepo raksasa.
Karakteristik:
- Support multi-language (Java, Go, Python, TypeScript, dll)
- Hermetic builds (reproducible)
- Remote caching dan distributed builds
Tradeoff:
- Learning curve tinggi
- Setup complex
- Overkill untuk monorepo kecil
CI/CD untuk Monorepo
Problem: Build Semua Project Lama
Di monorepo, tidak efisien build semua project setiap kali ada commit. Solusinya: detect affected projects.
Solusi: Turborepo + GitHub Actions
File .github/workflows/ci.yml:
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npx turbo run build test --filter=[HEAD^1]
Penjelasan:
--filter=[HEAD^1]: Hanya build project yang affected oleh commit terbaru
Best Practices Monorepo dengan Git
✅ Gunakan shallow clone untuk developer baru:
git clone --depth 1 <repo-url>
✅ Sparse checkout untuk large monorepo:
git sparse-checkout set apps/my-app
✅ Implement CODEOWNERS untuk ownership:
/apps/web/ @frontend-team
✅ Use Turborepo atau Nx untuk smart builds
✅ Setup CI/CD untuk hanya build yang affected
✅ Use conventional commits untuk clear changelog:
feat(ui-components): Add new Button variant
fix(auth-service): Fix token expiration bug
Kesimpulan
Monorepo adalah strategi powerful untuk mengelola multiple projects dalam satu repository. Dengan Git dan tools modern seperti Turborepo atau Nx, monorepo bisa scale tanpa masalah performance.
Key Takeaway:
- Monorepo cocok untuk project yang saling depend dan butuh tight integration
- Gunakan shallow clone dan sparse checkout untuk mempercepat clone
- Gunakan Turborepo atau Nx untuk smart builds dan caching
- Setup CI/CD untuk hanya build project yang affected
Di artikel berikutnya, kita akan membahas Git Performance Optimization untuk repository besar. Stay tuned!
Kiki/🎮🍉⌨️🍩💻