Skip to main content

Problem

Switching branches interrupts your workflow. You lose editor state, need to reinstall dependencies, and can’t easily compare implementations side-by-side. Working on multiple features or reviewing PRs requires constant context switching.

Solution

Git worktrees create separate working directories for different branches, all sharing the same repository. Each worktree has its own files, node_modules, and environment—letting you work on multiple branches simultaneously.

Implementation

Setup Script

Create a setup script that initializes worktrees with dependencies and environment files:
scripts/worktree-setup.sh
#!/usr/bin/env bash
# Setup a worktree with .env.local and deps
# Usage: worktree-setup.sh [branch-name]
#   No args: setup current worktree
#   With arg: create worktree + setup
set -e

MAIN_REPO=$(git worktree list | head -1 | awk '{print $1}')
REPO_NAME=$(basename "$MAIN_REPO")

if [ -n "$1" ]; then
  WORKTREE_PATH="../$REPO_NAME-$1"
  git worktree add -b "$1" "$WORKTREE_PATH" 2>/dev/null || git worktree add "$WORKTREE_PATH" "$1"
  cd "$WORKTREE_PATH"
fi

cp "$MAIN_REPO/.env.local" .env.local 2>/dev/null && echo "✓ .env.local" || echo "⚠ No .env.local"
bun i
echo "✓ Ready: $(pwd)"
Make it executable:
chmod +x scripts/worktree-setup.sh

IDE Integration (Cursor)

For Cursor IDE, add automatic dependency installation when opening worktrees:
.cursor/worktrees.json
{
  "setup-worktree": ["bun install"]
}

Git Aliases

Add these to your ~/.gitconfig for faster worktree commands:
~/.gitconfig
[alias]
    # List all worktrees
    wtl = worktree list

    # Add a new worktree (usage: git wta <branch-name>)
    wta = "!f() { repo=$(basename \"$(git worktree list --porcelain | sed -n '1s/^worktree //p')\"); git worktree add -b \"$1\" \"../$repo-$1\"; }; f"

    # Remove a worktree (usage: git wtr <path>)
    wtr = "!git worktree remove \"$@\" #"

    # Prune stale worktrees
    wtp = worktree prune

    # Cleanup merged branches and their worktrees
    wt-cleanup = "!f() { git fetch -p && git branch --merged ${1:-main} | grep -v \"^[* ]*${1:-main}$\" | while read branch; do wt=$(git worktree list | grep \"\\[$branch\\]\" | awk '{print $1}'); [ -n \"$wt\" ] && git worktree remove \"$wt\"; git branch -d \"$branch\"; done }; f"

Usage

Create a New Worktree

# Create worktree for a new branch
./scripts/worktree-setup.sh feature-auth

# Or use git alias
git wta feature-auth
This creates ../chatjs-feature-auth/ with:
  • Fresh checkout of the branch
  • Copied .env.local from main repo
  • Installed dependencies

Setup Existing Worktree

# In the worktree directory, run without args
./scripts/worktree-setup.sh

List Worktrees

git worktree list
# /home/user/chatjs              abc1234 [main]
# /home/user/chatjs-feature-auth def5678 [feature-auth]

Remove Worktree

# Remove worktree (keeps branch)
git worktree remove ../chatjs-feature-auth

# Force remove if there are changes
git worktree remove --force ../chatjs-feature-auth

Commands Reference

CommandDescription
git wta <branch>Add worktree for branch
git wtlList all worktrees
git wtr <path>Remove worktree
git wtpPrune stale worktrees
git wt-cleanupRemove merged branches and their worktrees