$ cat stop-cloning-your-repos-a-guide-to-git-worktrees-for-heavy-monoliths-and-ai-agents.md
# Stop Cloning Your Repos: A Guide to Git Worktrees for Heavy Monoliths and AI Agents
A practical guide to using git worktrees instead of repo clones for parallel development and AI coding agents, including a Docker/Postgres architecture for running heavy monolith stacks side-by-side without melting your laptop.
Stop Cloning Your Repos: A Guide to Git Worktrees for Heavy Monoliths and AI Agents
What is a Git Worktree?
A Git worktree allows you to check out multiple branches into completely separate physical folders on your hard drive, while sharing the exact same underlying .git database.
Think of it this way: a clone makes a completely independent, duplicated universe. A worktree just gives you a second physical desk to work on the exact same project.
The Visual Difference
❌ The Old Way: git clone Uses double the disk space. Commits don't sync locally.
Folder A: /my-app/ Folder B: /my-app-claude/
├── .git/ (1GB database) ├── .git/ (1GB database) ← Duplicated!
├── .env ├── .env
└── index.php └── index.php
✅ The New Way: git worktree Instant setup. Barely uses extra disk space. Commits sync instantly.
Folder A: /my-app/ Folder B: /my-app-claude/
├── .git/ (1GB database) ◄───── .git (1KB text file) ← Shared Brain!
├── .env ├── .env
└── index.php └── index.php
Because they share the same brain, a commit made in Folder B is instantly visible in Folder A's git log. No pushing or pulling required.
The "Simultaneous" Superpower
Because worktrees are separate folders, you can run multiple development servers side-by-side without them interfering with each other.
If you're using PHP/Laravel:
/my-app → php artisan serve --port=8000 # main branch
/my-app-claude → php artisan serve --port=8001 # Feature A
/my-app-codex → php artisan serve --port=8002 # Feature B
You can open three browser tabs and see three different branches of your code running live.
The "Gotcha": The Ignored Files Tax
Creating a worktree is easy:
git worktree add ../app-claude feature-a
But when you open that new folder, you might panic — your .env is gone, and your node_modules/ or vendor/ folders are missing.
This is a feature, not a bug. Git only copies tracked files into a new worktree. Anything in your .gitignore is intentionally left behind, which provides powerful environmental isolation:
- An agent can install a new NPM package in its worktree without breaking your main branch dependencies.
- You can run different versions of PHP or Node in different folders.
The trade-off is the Setup Tax — every time you create a worktree, you need to copy your .env and run npm install or composer install.
Pro tip: Don't create new worktrees every day. Instead, create 2–3 permanent ones (e.g.,
app-review,app-hotfix) and just swap branches inside them to reusenode_modules.
The Monolith Meltdown: Docker and Worktrees
If your app uses Docker, worktrees introduce a serious challenge.
A typical modern app doesn't just run one service — it might spin up a web container, a Postgres database, a Redis cache, and a LocalStack instance to emulate AWS services locally. If you run docker compose up in /my-app, Docker binds all of those to their respective ports. If an agent then tries to run docker compose up in its own worktree, Docker throws a "port already allocated" error and crashes.
You could work around this by offsetting ports in each .env file (e.g., DB_PORT=5433, REDIS_PORT=6380). That gives each worktree a fully isolated stack — but it doesn't scale.
The real problem: heavy services multiplied.
With your main app plus two agent worktrees each running their own full stack, you're suddenly running three copies of Postgres, three Redis instances, and three LocalStack containers simultaneously. Your machine will be gasping before a single line of code gets written.
The Solution: The Logical Database Architecture
Instead of duplicating the heavy infrastructure, run your shared services once and use Docker networks to let the separate worktrees connect to them.
To prevent agents from clobbering each other's data, create separate logical databases inside the single Postgres instance (Redis and LocalStack can typically be shared as-is, since they're either ephemeral or namespace-isolated):
┌─────────────────────────────────────────────────────────────┐
│ Your Laptop (CPU & RAM Saver) │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Shared Infrastructure (Runs Once) │ │
│ │ Postgres :5432 → db_main / db_claude / db_codex │ │
│ │ Redis :6379 → shared (keys namespaced per env) │ │
│ │ LocalStack :4566 → shared AWS emulation │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ /my-app → Web :8000 → db_main │
│ /app-claude → Web :8001 → db_claude │
│ /app-codex → Web :8002 → db_codex │
└─────────────────────────────────────────────────────────────┘
Setup steps:
-
Run the heavy lifting once. Start your shared services from
/my-appon a named Docker network. -
Create logical databases. Inside the running Postgres container:
CREATE DATABASE db_claude;
CREATE DATABASE db_codex;
-
Strip down the worktrees. In each agent's folder, remove Postgres, Redis, and LocalStack from
docker-compose.ymlentirely — they only need their lightweight web/app containers. -
Connect the wires. In each agent's
.env, point to the shared containers but use isolated databases where needed:
DB_HOST=shared_postgres_container_name
DB_PORT=5432
DB_DATABASE=db_claude
REDIS_HOST=shared_redis_container_name
REDIS_PORT=6379
REDIS_PREFIX=claude_
AWS_ENDPOINT=http://shared_localstack_container_name:4566
Summary
Git worktrees are the ultimate unlock for local development. By isolating your physical files while sharing your Git history, you can test complex features side-by-side, run multiple AI agents concurrently, and — with the right Docker architecture — do it all without turning your laptop into a space heater.