Submodules & Monorepos
Organize complex projects with multiple repositories or unified monorepos. Dits supports both patterns with optimizations for large-scale projects.
Submodules
Embed external repos in your project
- Independent versioning
- Shared across projects
- Pinned to specific commits
Monorepos
All code in one repository
- Atomic changes across packages
- Simplified dependencies
- Single source of truth
Submodules
Adding a Submodule
# Add a submodule
$ dits submodule add https://dits.example.com/shared-lib libs/shared
Cloning into 'libs/shared'...
done.
# This creates:
# - libs/shared/ directory with the submodule content
# - .ditsmodules file tracking the submodule
$ cat .ditsmodules
[submodule "libs/shared"]
path = libs/shared
url = https://dits.example.com/shared-libCloning with Submodules
# Clone and init submodules in one command
$ dits clone --recurse-submodules https://dits.example.com/main-project
# Or init after cloning
$ dits clone https://dits.example.com/main-project
$ cd main-project
$ dits submodule init
$ dits submodule updateUpdating Submodules
# Update all submodules to their tracked commits
$ dits submodule update
# Update to latest remote commits
$ dits submodule update --remote
# Update specific submodule
$ dits submodule update --remote libs/shared
# Pull latest for all submodules
$ dits submodule foreach 'dits pull origin main'Working Inside Submodules
# Make changes in submodule
$ cd libs/shared
$ dits checkout -b feature/update
# ... make changes ...
$ dits commit -m "Update shared lib"
$ dits push origin feature/update
# Back in main project, update reference
$ cd ../..
$ dits add libs/shared
$ dits commit -m "Update shared-lib to latest"
$ dits push origin mainSubmodule Commits
Submodules track specific commits, not branches. When you update a submodule, commit the change to record the new commit reference.
Removing Submodules
# Remove submodule
$ dits submodule deinit libs/shared
$ dits rm libs/shared
$ rm -rf .dits/modules/libs/shared
$ dits commit -m "Remove shared-lib submodule"Monorepo Structure
For projects where you want everything in one repository:
# Typical monorepo structure
my-project/
├── apps/
│ ├── web/ # Web application
│ ├── mobile/ # Mobile app
│ └── cli/ # Command-line tool
├── packages/
│ ├── core/ # Shared core library
│ ├── ui/ # UI component library
│ └── utils/ # Utility functions
├── assets/
│ ├── images/ # Shared images
│ └── videos/ # Video content
├── tools/
│ └── scripts/ # Build scripts
├── dits.toml
└── package.jsonSparse Checkout for Monorepos
Work on just the parts you need without downloading the entire repo:
# Clone metadata only
$ dits clone --filter blob:none https://dits.example.com/monorepo
$ cd monorepo
# Enable sparse checkout
$ dits sparse-checkout init --cone
# Check out only what you need
$ dits sparse-checkout set apps/web packages/core packages/ui
# Now only these directories have content
$ ls apps/
web/ # Only web is present
# Add more paths later
$ dits sparse-checkout add assets/images
# Show current sparse paths
$ dits sparse-checkout list
apps/web
packages/core
packages/ui
assets/imagesMonorepo with VFS
For very large monorepos, use VFS mounting for instant access:
# Clone metadata only
$ dits clone --filter blob:none https://dits.example.com/huge-monorepo
$ cd huge-monorepo
# Mount entire repo - files load on demand
$ dits mount /mnt/project
# Access any file instantly
$ ls /mnt/project/apps/web/
# Files appear immediately, content streams when accessed
# Work normally - your editor sees regular files
$ code /mnt/project/apps/web/Best of Both Worlds
Dits monorepos combine the organizational benefits of a single repo with the efficiency of only downloading what you need through sparse checkout and VFS.
Path-Based Permissions
Control access to different parts of your monorepo:
# .dits/access.toml
[permissions]
# Default: read for all authenticated users
default = "read"
# Write access by path
[permissions.write]
"apps/web" = ["web-team", "leads"]
"apps/mobile" = ["mobile-team", "leads"]
"packages/*" = ["core-team", "leads"]
"assets/videos" = ["content-team"]
# Admin access
[permissions.admin]
"*" = ["leads", "devops"]When to Use Which
| Scenario | Recommendation |
|---|---|
| Shared library across projects | Submodule |
| External dependency you fork | Submodule |
| Tightly coupled applications | Monorepo |
| Atomic refactors across packages | Monorepo |
| Independent release cycles | Submodule or separate repos |
| Game + assets + tools | Monorepo with sparse checkout |
Related Topics
- Repository Commands - Clone and init
- VFS Commands - Virtual filesystem mounting
- Large Files Guide - Binary asset management