Skip to content

Git Worktree Development

Git worktrees enable you to work on multiple branches simultaneously without constantly switching contexts. This is particularly useful for the Jubiloop monorepo where builds can take time and environment files need to be maintained.

What Are Git Worktrees?

Git worktrees allow you to have multiple working directories from the same repository, each checked out to different branches. Instead of switching branches in place (and potentially losing uncommitted work or having to rebuild), you can have separate directories for each feature you're working on.

Benefits for Jubiloop Development

  • Parallel Development: Work on multiple features simultaneously without context switching
  • Preserve Build Artifacts: Each worktree maintains its own node_modules and build outputs
  • Environment Isolation: Each worktree has its own .env files for different configurations
  • Quick Bug Fixes: Jump to a bugfix without stashing or committing work-in-progress
  • Testing Different Versions: Compare behavior across branches side-by-side
  • Faster Branch Switching: No need to rebuild when switching between worktrees

Quick Start

Initial Setup

First, make the worktree scripts executable:

bash
./scripts/setup-scripts.sh

This will:

  • Check for required dependencies (git, npm)
  • Create the worktrees directory structure
  • Set executable permissions on all scripts
  • Display available commands

Creating Your First Worktree

Create a new worktree for a feature branch:

bash
./scripts/worktree.sh feature/sc-187-new-feature

This automatically:

  • Creates a new branch from develop
  • Sets up a worktree in ../jubiloop-worktrees/feature-sc-187-new-feature
  • Copies all .env files from the main worktree
  • Copies editor configurations (Zed, VS Code, Cursor)
  • Opens the worktree in your preferred editor

Worktree Management Scripts

worktree.sh - Create and Set Up Worktrees

Creates a new worktree with automatic environment configuration.

bash
./scripts/worktree.sh <branch-name> [options]

Options:

  • -b, --base <branch> - Base branch to create from (default: develop or current)
  • -e, --copy-env-from <worktree> - Copy .env files from specified worktree (default: main)
  • -n, --no-editor - Don't open the worktree in an editor
  • -i, --install - Run npm install after creating worktree
  • -o, --open-dir - Open worktree directory in file manager

Examples:

bash
# Create feature branch from develop
./scripts/worktree.sh feature/sc-123-user-auth

# Create from specific base branch
./scripts/worktree.sh hotfix/critical -b main

# Create with npm install and open in file manager
./scripts/worktree.sh feature/new-ui -i -o

# Copy environment from another worktree
./scripts/worktree.sh feature/test -e feature/sc-123-user-auth

worktree-remove.sh - Safely Remove Worktrees

Removes worktrees with safety checks for uncommitted changes.

bash
./scripts/worktree-remove.sh <branch-name> [options]

Options:

  • -f, --force - Skip confirmation prompts (use with caution)

Safety Features:

  • Warns about uncommitted changes
  • Warns about unpushed commits
  • Asks for confirmation before deletion
  • Optionally deletes the associated branch
  • Cleans up orphaned worktree registrations

Example:

bash
# Remove with confirmations
./scripts/worktree-remove.sh feature/sc-123-user-auth

# Force remove (skip confirmations)
./scripts/worktree-remove.sh feature/old-feature -f

worktree-list.sh - View All Worktrees

Lists all worktrees with their status and configuration.

bash
./scripts/worktree-list.sh [options]

Options:

  • -v, --verbose - Show detailed environment file information

Information Displayed:

  • Branch name and location
  • Current worktree indicator
  • Clean/dirty status (uncommitted changes)
  • Environment file presence
  • Last commit information

Visual Indicators:

  • [MAIN] - Main worktree
  • ← YOU ARE HERE - Current worktree
  • - Present/clean
  • - Warning/partial
  • - Missing/error

Example:

bash
# Basic list
./scripts/worktree-list.sh

# Detailed view with env file sizes and line counts
./scripts/worktree-list.sh -v

worktree-switch.sh - Quick Switch Between Worktrees

Opens a different worktree in your editor without manual navigation.

bash
./scripts/worktree-switch.sh <branch-name>

Features:

  • Automatically opens in Zed or VS Code
  • Shows worktree status before switching
  • Displays current commit information
  • Lists available worktrees if branch not found

Example:

bash
# Switch to another worktree
./scripts/worktree-switch.sh develop

# Switch to main worktree
./scripts/worktree-switch.sh main

Common Workflows

Working on Multiple Features

When you need to work on several features simultaneously:

bash
# Create worktrees for each feature
./scripts/worktree.sh feature/sc-100-api-endpoints -i
./scripts/worktree.sh feature/sc-101-ui-components -i
./scripts/worktree.sh feature/sc-102-documentation

# List all worktrees to see status
./scripts/worktree-list.sh

# Switch between them as needed
./scripts/worktree-switch.sh feature/sc-100-api-endpoints

Emergency Hotfix

When you need to fix a critical bug while working on a feature:

bash
# Create hotfix worktree from main
./scripts/worktree.sh hotfix/critical-bug -b main -i

# After fixing and pushing
./scripts/worktree-remove.sh hotfix/critical-bug

# Return to your feature
./scripts/worktree-switch.sh feature/sc-100-api-endpoints

Testing Changes Across Branches

Compare behavior between branches:

bash
# Set up worktrees for comparison
./scripts/worktree.sh develop -i
./scripts/worktree.sh feature/new-implementation -i

# Run both simultaneously on different ports
cd ../jubiloop-worktrees/develop
npm run dev

# In another terminal
cd ../jubiloop-worktrees/feature-new-implementation
PORT=3001 npm run dev

Code Review Preparation

Review code locally before creating a PR:

bash
# Create worktree for the branch to review
./scripts/worktree.sh feature/sc-200-colleague-branch

# Open in editor to review
# The worktree is automatically opened

# Clean up after review
./scripts/worktree-remove.sh feature/sc-200-colleague-branch

Environment File Management

The scripts automatically handle environment files to ensure each worktree is ready to run:

Automatic Copying

When creating a worktree, the following files are copied:

  • apps/server/.env
  • apps/webapp/.env
  • apps/marketing/.env

Editor Configurations

These configurations are also copied:

  • .zed/ - Zed editor settings
  • .vscode/ - VS Code settings
  • .cursor/ - Cursor editor settings
  • .claude - Claude AI settings
  • CLAUDE.md - Claude instructions
  • .cursorignore - Cursor ignore patterns
  • .cursorrules - Cursor rules

Fallback Behavior

If .env files don't exist in the source:

  • Falls back to .env.example files
  • Warns you about missing configurations
  • Creates basic .env from examples

Directory Structure

Worktrees are organized in a sibling directory to keep the main repository clean:

parent-directory/
├── jubiloop/                    # Main repository
│   ├── apps/
│   ├── packages/
│   └── scripts/
│       ├── worktree.sh
│       ├── worktree-remove.sh
│       ├── worktree-list.sh
│       └── worktree-switch.sh

└── jubiloop-worktrees/          # All worktrees
    ├── feature-sc-100-api/      # Each branch gets its own directory
    ├── feature-sc-101-ui/       # Branch name with slashes replaced
    └── hotfix-critical-bug/     # Completely isolated workspace

Best Practices

When to Use Worktrees

Good Use Cases:

  • Working on long-running features
  • Reviewing colleague's code
  • Testing changes that require different configurations
  • Emergency fixes while preserving work in progress
  • Comparing behavior between versions

When NOT to Use:

  • Quick one-line fixes (just use regular branch switching)
  • When disk space is very limited
  • For branches you'll only visit once briefly

Naming Conventions

Follow the standard branch naming:

  • feature/sc-XXX-description for features
  • bugfix/sc-XXX-description for bugs
  • hotfix/description for urgent fixes

The scripts automatically sanitize branch names for filesystem compatibility.

Maintenance

Regular Cleanup:

bash
# List worktrees to see what's active
./scripts/worktree-list.sh

# Remove completed feature worktrees
./scripts/worktree-remove.sh feature/completed-feature

# Prune any broken references
git worktree prune

Disk Space: Each worktree includes:

  • Full copy of source code
  • Separate node_modules (can be 1-2GB)
  • Build artifacts

Consider removing unused worktrees to save space.

Troubleshooting

"Worktree already exists"

If you get this error, the worktree directory already exists:

bash
# Check existing worktrees
./scripts/worktree-list.sh

# Remove if needed
./scripts/worktree-remove.sh <branch-name>

Missing Environment Files

If .env files aren't copied:

bash
# Manually copy from main worktree
cp ../jubiloop/apps/server/.env ../jubiloop-worktrees/your-branch/apps/server/.env

Editor Not Opening

If the editor doesn't open automatically:

bash
# Check installed editors
which zed
which code

# Manually open
code ../jubiloop-worktrees/your-branch

Orphaned Worktrees

If a worktree directory was manually deleted:

bash
# Clean up git's worktree list
git worktree prune

# Or use the remove script
./scripts/worktree-remove.sh <branch-name>

Branch Conflicts

If the branch already exists:

bash
# The script will use the existing branch
./scripts/worktree.sh existing-branch

# Or create with a different name
./scripts/worktree.sh feature/sc-XXX-alternative

Advanced Usage

Custom Base Branches

Create worktrees from any branch or commit:

bash
# From a specific remote branch
./scripts/worktree.sh feature/new -b origin/experimental

# From current branch (useful when already in a worktree)
cd ../jubiloop-worktrees/feature-base
./scripts/worktree.sh feature/extension

Environment Variations

Test with different configurations:

bash
# Create worktree
./scripts/worktree.sh feature/test-config

# Modify environment for this specific worktree
cd ../jubiloop-worktrees/feature-test-config
vim apps/server/.env  # Edit for different API endpoint

Parallel Testing

Run multiple versions simultaneously:

bash
# Terminal 1: Development version
cd ../jubiloop-worktrees/develop
npm run dev

# Terminal 2: Feature version on different ports
cd ../jubiloop-worktrees/feature-new
PORT=4000 npm run dev:server
PORT=3001 npm run dev:webapp

Tips and Tricks

  1. Tab Completion: Use tab completion with branch names for faster navigation

  2. Aliases: Add to your shell config:

    bash
    alias wt='./scripts/worktree.sh'
    alias wts='./scripts/worktree-switch.sh'
    alias wtl='./scripts/worktree-list.sh'
    alias wtr='./scripts/worktree-remove.sh'
  3. Quick Status Check: Run ./scripts/worktree-list.sh regularly to track active work

  4. Shared npm Cache: npm cache is shared between worktrees, speeding up installs

  5. Git Commands: Regular git commands work in any worktree:

    bash
    cd ../jubiloop-worktrees/feature-branch
    git add .
    git commit -m "[sc-123] implement feature"
    git push origin feature-branch

Summary

Git worktrees provide a powerful way to manage parallel development in the Jubiloop monorepo. The custom scripts handle the complexity of environment setup, making it easy to:

  • Work on multiple features without context switching
  • Preserve build state and configurations
  • Quickly respond to urgent fixes
  • Review code without disrupting your work

Use worktrees whenever you need to maintain multiple working states or when switching branches would be disruptive to your current work.


Related Documentation:

Built with ❤️ by the Jubiloop team