# Git Worktrees: From Zero to Hero - A comprehensive guide to using Git worktrees with submodules

> Source: <https://gist.github.com/ashwch/946ad983977c9107db7ee9abafeb95bd>
> Published: 2025-08-07 05:32:31+00:00

# Git Worktrees: From Zero to Hero

## Table of Contents
1. [What Are Git Worktrees? (First Principles)](#what-are-git-worktrees-first-principles)
2. [The Problem Worktrees Solve](#the-problem-worktrees-solve)
3. [How Worktrees Work](#how-worktrees-work)
4. [Worktrees + Submodules: Monolith Setup](#worktrees--submodules-monolith-setup)
5. [Practical Tutorial: Creating Your First Worktree](#practical-tutorial-creating-your-first-worktree)
6. [Advanced Workflows](#advanced-workflows)
7. [Best Practices](#best-practices)
8. [Troubleshooting](#troubleshooting)
9. [For Non-Technical Stakeholders](#for-non-technical-stakeholders)

---

## What Are Git Worktrees? (First Principles)

### The Traditional Git Model
Normally, when you work with Git, you have:
- **One working directory** (the folder with your code)
- **One active branch** at a time
- **Switching branches** changes all files in that directory

```
my-project/
├── src/
├── README.md
└── .git/
```

When you run `git checkout feature-branch`, ALL files change to match that branch.

### The Worktree Model
Git worktrees let you have:
- **Multiple working directories** from the same repository
- **Different branches** checked out simultaneously
- **Independent work** in each directory

```
my-project/                    ← Main repo (main branch)
├── src/
├── README.md
└── .git/

my-project-feature-1/          ← Worktree 1 (feature-1 branch)
├── src/
├── README.md
└── .git                      ← File pointing to main repo

my-project-feature-2/          ← Worktree 2 (feature-2 branch)
├── src/
├── README.md
└── .git                      ← File pointing to main repo
```

### Key Insight
Think of worktrees as **parallel universes** of your code:
- Each universe (worktree) shows your project at a different point in time (branch/commit)
- Changes in one universe don't affect the others
- All universes share the same Git history (they're connected to the same `.git` repository)

---

## The Problem Worktrees Solve

### Without Worktrees (Traditional Workflow)
```bash
# Working on feature A
git checkout feature-a
# Make changes, test, etc.

# Need to quickly check feature B
git stash                    # Save current work
git checkout feature-b       # Switch context
# Look at feature B code

# Back to feature A
git checkout feature-a
git stash pop               # Restore work
# Continue where you left off
```

**Problems:**
- Context switching overhead
- Risk of losing uncommitted work
- Can't compare branches side-by-side
- Can't run tests on multiple branches simultaneously
- Interrupts your flow

### With Worktrees
```bash
# Create separate worktrees
git worktree add ../project-feature-a feature-a
git worktree add ../project-feature-b feature-b

# Work in parallel
cd ../project-feature-a     # Work on feature A
cd ../project-feature-b     # Work on feature B (in another terminal)
```

**Benefits:**
- No context switching
- Work on multiple features simultaneously
- Compare code side-by-side
- Run different tests in parallel
- Perfect for AI tools like Claude Code

---

## How Worktrees Work

### The Git Magic
When you create a worktree, Git:

1. **Creates a new directory** with all your project files
2. **Links it to the main repository** (shares Git history)
3. **Checks out a specific branch** in that directory
4. **Prevents conflicts** (same branch can't be checked out twice)

### Under the Hood
```
main-repo/
└── .git/
    ├── objects/           ← All Git data (shared)
    ├── refs/              ← Branch references (shared)
    └── worktrees/         ← Worktree metadata
        ├── worktree-1/
        └── worktree-2/

worktree-1/
├── your-files/            ← Working files (independent)
└── .git                   ← File pointing to main-repo/.git

worktree-2/
├── your-files/            ← Working files (independent)
└── .git                   ← File pointing to main-repo/.git
```

### The "One Branch Per Worktree" Rule
Git prevents the same branch from being checked out in multiple worktrees:
```bash
# This works
git worktree add ../repo-feature-a feature-a

# This fails if feature-a is already checked out
git worktree add ../repo-feature-a-copy feature-a
# Error: 'feature-a' is already checked out
```

This prevents confusion and conflicts.

---

## Worktrees + Submodules: Monolith Setup

### What Makes This Setup Special

A monolith repository can contain **multiple repositories as submodules**:
```
monolith/
├── frontend/              ← Git submodule (separate repo)
├── backend/               ← Git submodule (separate repo)
├── infrastructure/        ← Git submodule (separate repo)
├── shared-components/     ← Git submodule (separate repo)
└── .gitmodules           ← Submodule configuration
```

### The Challenge
When you create a worktree of a repository with submodules:
- The **main repository** gets a new worktree
- The **submodules** need to be initialized separately
- Each submodule can be on different branches in different worktrees

### Automation Solution
Create automation scripts to handle this complexity:
- [`create_worktree.py`](https://gist.github.com/ashwch/79177b4af7f2ea482418d6e9934d4787) - Creates worktrees with proper submodule setup
- [`update_submodules.py`](https://gist.github.com/ashwch/909ea473250e8c8a937a8a4aa4a4dc72) - Manages submodule updates

### Visual Example
```
monolith/                                     ← Main repo (main branch)
├── frontend/ (main branch)
├── backend/ (main branch)
└── infrastructure/ (main branch)

monolith-feature-123/                         ← Worktree (feature-123 branch)
├── frontend/ (feature-123-frontend branch)
├── backend/ (main branch)
└── infrastructure/ (feature-123-infra branch)
```

Notice how:
- Main repo worktree is on `feature-123` branch
- Each submodule can be on different branches
- This lets you work on related changes across multiple repositories

---

## Practical Tutorial: Creating Your First Worktree

### Prerequisites
```bash
# Make sure you're in the main repository
cd /path/to/your-monolith

# Check current setup
git status
git worktree list
```

### Method 1: Using Automated Script (Recommended)

```bash
# Run smart worktree creation script
python scripts/create_worktree.py
# or with uv: uv run scripts/create_worktree.py
```

**What this script does:**
1. **Asks for a worktree name** (suggests smart defaults)
2. **Shows available branches** for main repo (with search)
3. **For each submodule**, lets you choose which branch to use
4. **Creates the worktree** one directory above current location
5. **Initializes all submodules** with your chosen branches
6. **Handles conflicts** gracefully

**Example interaction:**
```
Enter worktree name (e.g., 'feature-auth'): feature-oauth
Creating worktree: ../monolith-feature-oauth

Select branch for main repository:
[1] main
[2] feature/oauth-integration
[3] develop
Choice: 2

Select branch for frontend submodule:
[1] main
[2] feature/oauth-ui
[3] develop
Choice: 2

... (continues for each submodule)

✅ Worktree created successfully!
📁 Location: ../monolith-feature-oauth
🌳 Branch: feature/oauth-integration
```

### Method 2: Manual Creation (Educational)

#### Step 1: Create the Basic Worktree
```bash
# Create worktree in parent directory
git worktree add ../monolith-feature-oauth feature/oauth-integration

# Navigate to the new worktree
cd ../monolith-feature-oauth
```

#### Step 2: Initialize Submodules
```bash
# Initialize all submodules (this takes time)
git submodule update --init --recursive

# Check what branches submodules are on
git submodule foreach 'echo "Submodule: $name, Branch: $(git branch --show-current)"'
```

#### Step 3: Set Up Submodule Branches (Optional)
```bash
# Switch submodules to feature branches if needed
cd frontend
git checkout feature/oauth-ui
cd ../backend
git checkout main  # or whatever branch you need
cd ../infrastructure
git checkout feature/oauth-config
cd ..
```

### Verify Your Setup
```bash
# Check worktree status
git worktree list

# Check branch in main repo
git branch --show-current

# Check submodule branches
git submodule foreach 'echo "$name: $(git branch --show-current)"'
```

---

## Advanced Workflows

### Working Across Multiple Worktrees

#### Scenario: Comparing Two Feature Implementations
```bash
# Create two worktrees for comparison
python scripts/create_worktree.py  # Create approach-a
python scripts/create_worktree.py  # Create approach-b

# Work in parallel
cd ../monolith-approach-a
# Implement solution A

cd ../monolith-approach-b  
# Implement solution B

# Compare side-by-side in your IDE
code ../monolith-approach-a ../monolith-approach-b
```

#### Scenario: AI-Assisted Development
```bash
# Create worktree for AI session
python scripts/create_worktree.py

# In the new worktree, run Claude Code
cd ../monolith-feature-ai-assist
claude

# Meanwhile, continue manual work in main repo
cd /path/to/monolith
# Continue your work without interruption
```

### Managing Submodule Changes

#### Making Changes Across Multiple Repos
```bash
# In your worktree
cd ../monolith-feature-123

# Make changes in frontend
cd frontend
git checkout -b feature-123-frontend
# Make changes
git add . && git commit -m "Frontend changes for feature 123"
git push origin feature-123-frontend

# Make changes in backend
cd ../backend
git checkout -b feature-123-backend
# Make changes
git add . && git commit -m "Backend changes for feature 123"
git push origin feature-123-backend

# Update monolith to point to new commits
cd ..
git add frontend backend
git commit -m "Update submodules for feature 123"
git push origin feature-123
```

#### Updating Submodules from Remote
```bash
# Use update script
python scripts/update_submodules.py

# Or manually
git submodule update --recursive --remote
```

### Cleaning Up Worktrees

#### When Feature is Complete
```bash
# List all worktrees
git worktree list

# Remove completed worktree
git worktree remove ../monolith-feature-123

# Clean up any leftover references
git worktree prune
```

---

## Best Practices

### Naming Conventions
```bash
# Good worktree names
../monolith-feature-auth           # Feature-based
../monolith-bugfix-12345          # Issue-based
../monolith-hotfix-critical       # Purpose-based
../monolith-experiment-new-arch   # Experiment-based

# Avoid
../temp                           # Too generic
../test                          # Unclear purpose
../monolith                      # Confusing with main
```

### Directory Organization
```bash
# Recommended structure
projects/
├── monolith/                    ← Main repository
├── monolith-feature-auth/       ← Feature worktree
├── monolith-feature-payments/   ← Another feature
└── monolith-hotfix-urgent/      ← Hotfix worktree
```

### Branch Strategy
```bash
# Main repository branches
main                             ← Production
develop                          ← Integration
feature/auth-system             ← Feature branch
hotfix/critical-bug             ← Hotfix branch

# Submodule branches (can be independent)
frontend: feature/auth-ui
backend: feature/auth-api
infrastructure: main            ← Unchanged for this feature
```

### Workflow Tips

#### 1. One Worktree Per Feature
- Don't reuse worktrees for different features
- Create new worktrees for each major task
- Clean up when done

#### 2. Initialize Submodules Immediately
```bash
# Always run after creating worktree
git submodule update --init --recursive
```

#### 3. Use Automation Scripts
```bash
# Let automation handle complexity
python create_worktree.py  # Download from: https://gist.github.com/ashwch/79177b4af7f2ea482418d6e9934d4787
python update_submodules.py # Download from: https://gist.github.com/ashwch/909ea473250e8c8a937a8a4aa4a4dc72
```

#### 4. Regular Cleanup
```bash
# Weekly cleanup of old worktrees
git worktree list
git worktree remove ../old-worktree-name
git worktree prune
```

---

## Troubleshooting

### Common Issues and Solutions

#### Issue: "Branch is already checked out"
```bash
# Error when trying to create worktree
fatal: 'main' is already checked out at '/path/to/monolith'

# Solution: Use a different branch or create new branch
git worktree add ../monolith-new -b new-branch-name main
```

#### Issue: Submodules Not Initialized
```bash
# Symptoms: Empty submodule directories
ls frontend/  # Empty

# Solution: Initialize submodules
git submodule update --init --recursive
```

#### Issue: Submodule in Wrong Branch
```bash
# Check current branches
git submodule foreach 'echo "$name: $(git branch --show-current)"'

# Fix: Switch to correct branch
cd problematic-submodule
git checkout correct-branch
cd ..
```

#### Issue: Can't Remove Worktree
```bash
# Error: worktree contains modified or untracked files
git worktree remove ../old-worktree

# Solution: Force removal (loses uncommitted changes!)
git worktree remove --force ../old-worktree
```

#### Issue: Submodule Conflicts During Merge
```bash
# When merging between branches with different submodule commits
# Solution: Choose which submodule commits to keep
git add problematic-submodule
git commit -m "Resolve submodule conflicts"
```

### Performance Tips

#### Large Repository Optimization
```bash
# Speed up submodule operations
git config submodule.recurse true
git config diff.submodule log
git config status.submodulesummary 1
```

#### Disk Space Management
```bash
# Share objects between worktrees (done automatically)
# But be aware: multiple worktrees = multiple working copies

# Check disk usage
du -sh ../monolith*
```

---

## For Non-Technical Stakeholders

### What This Means for You

#### The Problem We Solved
Imagine you're writing a document and need to:
- Work on Chapter 1 revisions
- Also draft Chapter 5
- Compare two different approaches for Chapter 3

Traditionally, you'd have to:
1. Save Chapter 1 work
2. Switch to Chapter 5
3. Save Chapter 5 work
4. Switch to Chapter 3
5. Go back and forth constantly

This is inefficient and error-prone.

#### Our Solution: Git Worktrees
Now we can have:
- **Document-v1/** folder for Chapter 1 work
- **Document-v2/** folder for Chapter 5 work  
- **Document-experiment/** folder for Chapter 3 approaches

All folders stay synchronized with the main document, but you can work on different parts independently.

### Business Benefits

#### 1. Faster Development
- **No context switching delays** - developers stay in flow
- **Parallel development** - multiple features simultaneously
- **Reduced merge conflicts** - isolated work streams

#### 2. Better Quality
- **Side-by-side comparisons** - easy to evaluate approaches
- **Isolated testing** - test features without affecting others
- **Safer experimentation** - try ideas without risk

#### 3. Enhanced Collaboration
- **AI tools work better** - can analyze multiple implementations
- **Code reviews easier** - compare implementations directly
- **Knowledge sharing** - team members can see different approaches

### Impact on Project Timelines

#### Before Worktrees
```
Week 1: Start Feature A
Week 2: Urgent bug interrupt → Switch context → Fix bug
Week 3: Return to Feature A → Re-understand code → Continue
Week 4: Complete Feature A
```
**Total: 4 weeks for Feature A + 1 bug fix**

#### With Worktrees
```
Week 1: Start Feature A (main worktree)
Week 2: Urgent bug → Create hotfix worktree → Fix bug in parallel
Week 3: Complete Feature A (uninterrupted) + Complete bug fix
Week 4: Start Feature B
```
**Total: 3 weeks for Feature A + 1 bug fix + start Feature B**

### What You'll Notice

#### As a Product Manager
- **Faster feature delivery** - less time lost to context switching
- **Better estimations** - developers can work more predictably
- **Easier demonstrations** - can show multiple versions side-by-side

#### As a Designer
- **Quick iterations** - developers can implement multiple design approaches
- **Live comparisons** - see different implementations running simultaneously
- **Faster feedback loops** - no delay switching between versions

#### As a Stakeholder
- **More reliable timelines** - fewer interruptions and delays
- **Higher quality output** - easier to compare and choose best solutions
- **Reduced risk** - experiments don't affect main development

---

## Summary

Git worktrees with submodules give us superpowers:

1. **Multiple parallel universes** of our codebase
2. **No context switching** between features
3. **AI tools work better** with isolated environments
4. **Complex projects simplified** through automation
5. **Team productivity increased** through better workflows

### Key Commands to Remember
```bash
# Create worktree (automated)
python scripts/create_worktree.py

# List worktrees
git worktree list

# Remove worktree
git worktree remove ../worktree-name

# Update submodules
python scripts/update_submodules.py
```

### Next Steps
1. Try creating your first worktree with our script
2. Experiment with parallel development
3. Use worktrees for your next feature
4. Share this guide with your team
5. Contribute improvements to automation scripts

---

*This guide covers Git worktrees with submodules for modern development workflows. Questions? Contributions welcome!*
