git-worktree

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Git Worktree Skill

Git Worktree 实用技巧

Manage parallel development environments using git worktrees with seamless terminal integration.
通过Git worktree结合无缝终端集成,管理并行开发环境。

Overview

概述

Git worktrees enable multiple working directories from a single repository:
  • Isolated feature development without branch switching
  • Run multiple Claude Code instances in parallel
  • Context switching without stashing uncommitted changes
  • Clean separation of experimental work
Git worktree允许从单个仓库创建多个工作目录:
  • 无需切换分支即可进行隔离的功能开发
  • 并行运行多组Claude Code实例
  • 无需暂存未提交更改即可切换开发上下文
  • 清晰分离实验性开发工作

Quick Commands

快速命令

wt - Worktree Manager

wt - Worktree 管理器

The
wt
command creates worktrees with automatic terminal integration:
bash
undefined
wt
命令可创建worktree并自动集成终端:
bash
undefined

Create worktree with tmux window

Create worktree with tmux window

wt add-new-feature
wt add-new-feature

This will:

This will:

1. Create git worktree named 'add-new-feature'

1. Create git worktree named 'add-new-feature'

2. Create new tmux window in current session

2. Create new tmux window in current session

3. Rename window to 'add-new-feature'

3. Rename window to 'add-new-feature'

4. Change directory to the worktree

4. Change directory to the worktree

undefined
undefined

tmux Integration

tmux集成

Workflow: Create Worktree + tmux Window

工作流:创建Worktree + tmux窗口

bash
undefined
bash
undefined

Function for ~/.zshrc or ~/.bashrc

Function for ~/.zshrc or ~/.bashrc

wt() { local name="$1" local base_branch="${2:-main}" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Validate we're in a git repo
if [[ -z "$repo_root" ]]; then
    echo "Error: Not in a git repository"
    return 1
fi

# Create worktree directory
mkdir -p "$repo_root/.worktrees"

# Create worktree with new branch
if git worktree add -b "$name" "$worktree_path" "$base_branch" 2>/dev/null; then
    echo "Created worktree: $worktree_path"
elif git worktree add "$worktree_path" "$name" 2>/dev/null; then
    echo "Attached to existing branch: $name"
else
    echo "Error: Failed to create worktree"
    return 1
fi

# tmux integration
if [[ -n "$TMUX" ]]; then
    # Create new window with worktree name
    tmux new-window -n "$name" -c "$worktree_path"
    echo "Created tmux window: $name"
else
    # Not in tmux, just cd
    cd "$worktree_path"
    echo "Changed to: $worktree_path"
fi
}
wt() { local name="$1" local base_branch="${2:-main}" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Validate we're in a git repo
if [[ -z "$repo_root" ]]; then
    echo "Error: Not in a git repository"
    return 1
fi

# Create worktree directory
mkdir -p "$repo_root/.worktrees"

# Create worktree with new branch
if git worktree add -b "$name" "$worktree_path" "$base_branch" 2>/dev/null; then
    echo "Created worktree: $worktree_path"
elif git worktree add "$worktree_path" "$name" 2>/dev/null; then
    echo "Attached to existing branch: $name"
else
    echo "Error: Failed to create worktree"
    return 1
fi

# tmux integration
if [[ -n "$TMUX" ]]; then
    # Create new window with worktree name
    tmux new-window -n "$name" -c "$worktree_path"
    echo "Created tmux window: $name"
else
    # Not in tmux, just cd
    cd "$worktree_path"
    echo "Changed to: $worktree_path"
fi
}

Remove worktree and tmux window

Remove worktree and tmux window

wt-rm() { local name="$1" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Remove git worktree
git worktree remove "$worktree_path" --force 2>/dev/null

# Close tmux window if exists
if [[ -n "$TMUX" ]]; then
    tmux kill-window -t "$name" 2>/dev/null
fi

# Optionally delete branch
git branch -d "$name" 2>/dev/null

echo "Removed worktree: $name"
}
wt-rm() { local name="$1" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Remove git worktree
git worktree remove "$worktree_path" --force 2>/dev/null

# Close tmux window if exists
if [[ -n "$TMUX" ]]; then
    tmux kill-window -t "$name" 2>/dev/null
fi

# Optionally delete branch
git branch -d "$name" 2>/dev/null

echo "Removed worktree: $name"
}

List all worktrees

List all worktrees

wt-ls() { git worktree list }
undefined
wt-ls() { git worktree list }
undefined

tmux Session Management

tmux会话管理

bash
undefined
bash
undefined

Create dedicated tmux session per project

Create dedicated tmux session per project

wt-session() { local name="$1" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Create worktree first
wt "$name"

# Create new tmux session (or attach if exists)
if tmux has-session -t "$name" 2>/dev/null; then
    tmux attach-session -t "$name"
else
    tmux new-session -d -s "$name" -c "$worktree_path"
    tmux attach-session -t "$name"
fi
}
undefined
wt-session() { local name="$1" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Create worktree first
wt "$name"

# Create new tmux session (or attach if exists)
if tmux has-session -t "$name" 2>/dev/null; then
    tmux attach-session -t "$name"
else
    tmux new-session -d -s "$name" -c "$worktree_path"
    tmux attach-session -t "$name"
fi
}
undefined

iTerm2 Integration

iTerm2集成

AppleScript for iTerm2 Tabs

用于iTerm2标签页的AppleScript

bash
undefined
bash
undefined

Function for ~/.zshrc

Function for ~/.zshrc

wt-iterm() { local name="$1" local base_branch="${2:-main}" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Create worktree
mkdir -p "$repo_root/.worktrees"
git worktree add -b "$name" "$worktree_path" "$base_branch" 2>/dev/null || \
git worktree add "$worktree_path" "$name" 2>/dev/null

# Open in new iTerm2 tab
osascript <<EOF
tell application "iTerm2" tell current window create tab with default profile tell current session write text "cd '$worktree_path' && clear" end tell end tell end tell EOF
echo "Created worktree with iTerm2 tab: $name"
}
wt-iterm() { local name="$1" local base_branch="${2:-main}" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Create worktree
mkdir -p "$repo_root/.worktrees"
git worktree add -b "$name" "$worktree_path" "$base_branch" 2>/dev/null || \
git worktree add "$worktree_path" "$name" 2>/dev/null

# Open in new iTerm2 tab
osascript <<EOF
tell application "iTerm2" tell current window create tab with default profile tell current session write text "cd '$worktree_path' && clear" end tell end tell end tell EOF
echo "Created worktree with iTerm2 tab: $name"
}

Open worktree in new iTerm2 window

Open worktree in new iTerm2 window

wt-iterm-window() { local name="$1" local base_branch="${2:-main}" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Create worktree
mkdir -p "$repo_root/.worktrees"
git worktree add -b "$name" "$worktree_path" "$base_branch" 2>/dev/null || \
git worktree add "$worktree_path" "$name" 2>/dev/null

# Open in new iTerm2 window
osascript <<EOF
tell application "iTerm2" create window with default profile tell current session of current window write text "cd '$worktree_path' && clear" end tell end tell EOF
echo "Created worktree with iTerm2 window: $name"
}
undefined
wt-iterm-window() { local name="$1" local base_branch="${2:-main}" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Create worktree
mkdir -p "$repo_root/.worktrees"
git worktree add -b "$name" "$worktree_path" "$base_branch" 2>/dev/null || \
git worktree add "$worktree_path" "$name" 2>/dev/null

# Open in new iTerm2 window
osascript <<EOF
tell application "iTerm2" create window with default profile tell current session of current window write text "cd '$worktree_path' && clear" end tell end tell EOF
echo "Created worktree with iTerm2 window: $name"
}
undefined

iTerm2 Profile Integration

iTerm2配置文件集成

Create a dedicated iTerm2 profile for worktrees:
json
{
  "Name": "Worktree",
  "Badge Text": "WT: \\(session.name)",
  "Working Directory": "$HOME/.worktrees",
  "Custom Directory": "Yes"
}
为worktree创建专用的iTerm2配置文件:
json
{
  "Name": "Worktree",
  "Badge Text": "WT: \\(session.name)",
  "Working Directory": "$HOME/.worktrees",
  "Custom Directory": "Yes"
}

Configuration

配置

Environment Variables

环境变量

bash
undefined
bash
undefined

Add to ~/.zshrc or ~/.bashrc

Add to ~/.zshrc or ~/.bashrc

Preferred terminal for worktree operations (auto-detected if not set)

Preferred terminal for worktree operations (auto-detected if not set)

export WORKTREE_TERMINAL="tmux" # or "iterm2" or "auto"
export WORKTREE_TERMINAL="tmux" # or "iterm2" or "auto"

Auto-install dependencies after creating worktree

Auto-install dependencies after creating worktree

export WORKTREE_AUTO_INSTALL=true
undefined
export WORKTREE_AUTO_INSTALL=true
undefined

Worktree Location

Worktree存储位置

Worktrees are stored inside the project directory:
~/Repos/github/my-project/
├── .worktrees/
│   ├── feature-auth/      # worktree for feature-auth branch
│   ├── bugfix-login/      # worktree for bugfix-login branch
│   └── add-new-skill/     # worktree for add-new-skill branch
├── src/
├── package.json
└── ...
Worktrees存储在项目目录内部
~/Repos/github/my-project/
├── .worktrees/
│   ├── feature-auth/      # worktree for feature-auth branch
│   ├── bugfix-login/      # worktree for bugfix-login branch
│   └── add-new-skill/     # worktree for add-new-skill branch
├── src/
├── package.json
└── ...

Shell Configuration

Shell配置

Functions are defined in
~/.zsh/functions.zsh
(already loaded by your zshrc):
zsh
undefined
函数定义在
~/.zsh/functions.zsh
中(已由zshrc自动加载):
zsh
undefined

Functions location: ~/.zsh/functions.zsh

Functions location: ~/.zsh/functions.zsh

Aliases

Aliases

alias wt='wt' alias wtl='wt-ls' alias wtr='wt-rm' alias wts='wt-session'
alias wt='wt' alias wtl='wt-ls' alias wtr='wt-rm' alias wts='wt-session'

Completion for wt commands

Completion for wt commands

_wt_completion() { local branches=$(git branch --format='%(refname:short)' 2>/dev/null) local worktrees=$(git worktree list --porcelain 2>/dev/null | grep '^worktree' | cut -d' ' -f2 | xargs -I{} basename {}) _alternative
"branches:branch:($branches)"
"worktrees:worktree:($worktrees)" } compdef _wt_completion wt wt-rm
undefined
_wt_completion() { local branches=$(git branch --format='%(refname:short)' 2>/dev/null) local worktrees=$(git worktree list --porcelain 2>/dev/null | grep '^worktree' | cut -d' ' -f2 | xargs -I{} basename {}) _alternative
"branches:branch:($branches)"
"worktrees:worktree:($worktrees)" } compdef _wt_completion wt wt-rm
undefined

Git Worktree Commands Reference

Git Worktree命令参考

Creating Worktrees

创建Worktree

bash
undefined
bash
undefined

Create worktree with new branch from current HEAD

Create worktree with new branch from current HEAD

git worktree add ../feature-x -b feature-x
git worktree add ../feature-x -b feature-x

Create worktree from specific branch

Create worktree from specific branch

git worktree add ../hotfix hotfix-branch
git worktree add ../hotfix hotfix-branch

Create worktree from remote branch

Create worktree from remote branch

git worktree add ../upstream upstream/main
git worktree add ../upstream upstream/main

Create worktree at specific commit

Create worktree at specific commit

git worktree add ../review abc123
undefined
git worktree add ../review abc123
undefined

Managing Worktrees

管理Worktree

bash
undefined
bash
undefined

List all worktrees

List all worktrees

git worktree list
git worktree list

Show worktree details (porcelain format)

Show worktree details (porcelain format)

git worktree list --porcelain
git worktree list --porcelain

Lock worktree (prevent pruning)

Lock worktree (prevent pruning)

git worktree lock ../feature-x --reason "WIP"
git worktree lock ../feature-x --reason "WIP"

Unlock worktree

Unlock worktree

git worktree unlock ../feature-x
git worktree unlock ../feature-x

Remove worktree

Remove worktree

git worktree remove ../feature-x
git worktree remove ../feature-x

Force remove (discards changes)

Force remove (discards changes)

git worktree remove ../feature-x --force
git worktree remove ../feature-x --force

Prune stale worktrees

Prune stale worktrees

git worktree prune
undefined
git worktree prune
undefined

Advanced Operations

高级操作

bash
undefined
bash
undefined

Move worktree to new location

Move worktree to new location

git worktree move ../old-path ../new-path
git worktree move ../old-path ../new-path

Repair worktree after manual move

Repair worktree after manual move

git worktree repair ../moved-worktree
undefined
git worktree repair ../moved-worktree
undefined

Parallel Claude Development

并行Claude开发

Running Multiple Instances

运行多组实例

bash
undefined
bash
undefined

Create worktrees for parallel development

Create worktrees for parallel development

wt feature-auth wt feature-api wt bugfix-login
wt feature-auth wt feature-api wt bugfix-login

Each worktree gets its own:

Each worktree gets its own:

- tmux window / iTerm2 tab

- tmux window / iTerm2 tab

- Git index and working directory

- Git index and working directory

- Port allocation (if configured)

- Port allocation (if configured)

- Claude Code instance

- Claude Code instance

undefined
undefined

Port Management

端口管理

bash
undefined
bash
undefined

Configure port pools per worktree

Configure port pools per worktree

export WORKTREE_PORT_BASE=8100 export WORKTREE_PORTS_PER_TREE=2
export WORKTREE_PORT_BASE=8100 export WORKTREE_PORTS_PER_TREE=2

Calculate ports for worktree

Calculate ports for worktree

get_worktree_ports() { local index=$(git worktree list | grep -n "$PWD" | cut -d: -f1) local base=$((WORKTREE_PORT_BASE + (index - 1) * WORKTREE_PORTS_PER_TREE)) echo "Dev server: $base, API: $((base + 1))" }
undefined
get_worktree_ports() { local index=$(git worktree list | grep -n "$PWD" | cut -d: -f1) local base=$((WORKTREE_PORT_BASE + (index - 1) * WORKTREE_PORTS_PER_TREE)) echo "Dev server: $base, API: $((base + 1))" }
undefined

Cleanup Workflows

清理工作流

Merge and Cleanup

合并后清理

bash
undefined
bash
undefined

After PR merge, clean up worktree

After PR merge, clean up worktree

wt-cleanup() { local name="$1" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Switch to main worktree
cd "$repo_root"

# Update main
git fetch origin
git pull origin main

# Remove worktree
git worktree remove "$worktree_path" --force

# Delete branch if merged
if git branch --merged | grep -q "$name"; then
    git branch -d "$name"
    echo "Branch $name was merged and deleted"
else
    echo "Branch $name not yet merged, kept locally"
fi

# Close tmux window
[[ -n "$TMUX" ]] && tmux kill-window -t "$name" 2>/dev/null
}
undefined
wt-cleanup() { local name="$1" local repo_root=$(git rev-parse --show-toplevel 2>/dev/null) local worktree_path="$repo_root/.worktrees/$name"
# Switch to main worktree
cd "$repo_root"

# Update main
git fetch origin
git pull origin main

# Remove worktree
git worktree remove "$worktree_path" --force

# Delete branch if merged
if git branch --merged | grep -q "$name"; then
    git branch -d "$name"
    echo "Branch $name was merged and deleted"
else
    echo "Branch $name not yet merged, kept locally"
fi

# Close tmux window
[[ -n "$TMUX" ]] && tmux kill-window -t "$name" 2>/dev/null
}
undefined

Bulk Cleanup

批量清理

bash
undefined
bash
undefined

Remove all worktrees with merged branches

Remove all worktrees with merged branches

wt-cleanup-merged() { local main_dir=$(git worktree list | head -1 | awk '{print $1}')
git worktree list | tail -n +2 | while read -r line; do
    local wt_path=$(echo "$line" | awk '{print $1}')
    local wt_branch=$(echo "$line" | awk '{print $3}' | tr -d '[]')

    if git branch --merged main | grep -q "$wt_branch"; then
        echo "Removing merged worktree: $wt_branch"
        git worktree remove "$wt_path" --force
        git branch -d "$wt_branch"
    fi
done
}
undefined
wt-cleanup-merged() { local main_dir=$(git worktree list | head -1 | awk '{print $1}')
git worktree list | tail -n +2 | while read -r line; do
    local wt_path=$(echo "$line" | awk '{print $1}')
    local wt_branch=$(echo "$line" | awk '{print $3}' | tr -d '[]')

    if git branch --merged main | grep -q "$wt_branch"; then
        echo "Removing merged worktree: $wt_branch"
        git worktree remove "$wt_path" --force
        git branch -d "$wt_branch"
    fi
done
}
undefined

Troubleshooting

故障排除

Common Issues

常见问题

Worktree already exists:
bash
undefined
Worktree已存在:
bash
undefined

List existing worktrees

List existing worktrees

git worktree list
git worktree list

Remove stale entry

Remove stale entry

git worktree prune

**Branch already checked out:**
```bash
git worktree prune

**分支已被检出:**
```bash

Error: 'branch' is already checked out at '/path'

Error: 'branch' is already checked out at '/path'

Solution: Use a different branch name or remove existing worktree

Solution: Use a different branch name or remove existing worktree

git worktree remove /path/to/existing

**tmux window naming conflicts:**
```bash
git worktree remove /path/to/existing

**tmux窗口命名冲突:**
```bash

Rename existing window first

Rename existing window first

tmux rename-window -t old-name new-name
tmux rename-window -t old-name new-name

Or kill conflicting window

Or kill conflicting window

tmux kill-window -t conflicting-name

**iTerm2 AppleScript errors:**
```bash
tmux kill-window -t conflicting-name

**iTerm2 AppleScript错误:**
```bash

Ensure iTerm2 is running

Ensure iTerm2 is running

open -a iTerm
open -a iTerm

Grant automation permissions

Grant automation permissions

System Preferences > Security & Privacy > Privacy > Automation

System Preferences > Security & Privacy > Privacy > Automation

undefined
undefined

References

参考资料

  • references/tmux-config.md - tmux configuration for worktrees
  • references/iterm2-config.md - iTerm2 profile setup
  • Shell functions:
    ~/.zsh/functions.zsh
  • references/tmux-config.md - tmux configuration for worktrees
  • references/iterm2-config.md - iTerm2 profile setup
  • Shell functions:
    ~/.zsh/functions.zsh

External Links

外部链接