git-worktree
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGit 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 command creates worktrees with automatic terminal integration:
wtbash
undefinedwtbash
undefinedCreate 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
undefinedundefinedtmux Integration
tmux集成
Workflow: Create Worktree + tmux Window
工作流:创建Worktree + tmux窗口
bash
undefinedbash
undefinedFunction 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
}
undefinedwt-ls() {
git worktree list
}
undefinedtmux Session Management
tmux会话管理
bash
undefinedbash
undefinedCreate 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}
undefinedwt-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}
undefinediTerm2 Integration
iTerm2集成
AppleScript for iTerm2 Tabs
用于iTerm2标签页的AppleScript
bash
undefinedbash
undefinedFunction 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 <<EOFtell 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 <<EOFtell 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 <<EOFtell 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"}
undefinedwt-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 <<EOFtell 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"}
undefinediTerm2 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
undefinedbash
undefinedAdd 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
undefinedexport WORKTREE_AUTO_INSTALL=true
undefinedWorktree 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 (already loaded by your zshrc):
~/.zsh/functions.zshzsh
undefined函数定义在中(已由zshrc自动加载):
~/.zsh/functions.zshzsh
undefinedFunctions 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
"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
"branches:branch:($branches)"
"worktrees:worktree:($worktrees)" } compdef _wt_completion wt wt-rm
undefinedGit Worktree Commands Reference
Git Worktree命令参考
Creating Worktrees
创建Worktree
bash
undefinedbash
undefinedCreate 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
undefinedgit worktree add ../review abc123
undefinedManaging Worktrees
管理Worktree
bash
undefinedbash
undefinedList 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
undefinedgit worktree prune
undefinedAdvanced Operations
高级操作
bash
undefinedbash
undefinedMove 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
undefinedgit worktree repair ../moved-worktree
undefinedParallel Claude Development
并行Claude开发
Running Multiple Instances
运行多组实例
bash
undefinedbash
undefinedCreate 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
undefinedundefinedPort Management
端口管理
bash
undefinedbash
undefinedConfigure 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))"
}
undefinedget_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))"
}
undefinedCleanup Workflows
清理工作流
Merge and Cleanup
合并后清理
bash
undefinedbash
undefinedAfter 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}
undefinedwt-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}
undefinedBulk Cleanup
批量清理
bash
undefinedbash
undefinedRemove 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}
undefinedwt-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}
undefinedTroubleshooting
故障排除
Common Issues
常见问题
Worktree already exists:
bash
undefinedWorktree已存在:
bash
undefinedList existing worktrees
List existing worktrees
git worktree list
git worktree list
Remove stale entry
Remove stale entry
git worktree prune
**Branch already checked out:**
```bashgit worktree prune
**分支已被检出:**
```bashError: '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:**
```bashgit worktree remove /path/to/existing
**tmux窗口命名冲突:**
```bashRename 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:**
```bashtmux kill-window -t conflicting-name
**iTerm2 AppleScript错误:**
```bashEnsure 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
undefinedundefinedReferences
参考资料
- 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
外部链接
- Git Worktree Documentation: https://git-scm.com/docs/git-worktree
- tmux Manual: https://man.openbsd.org/tmux
- iTerm2 Documentation: https://iterm2.com/documentation.html
- Git Worktree Documentation: https://git-scm.com/docs/git-worktree
- tmux Manual: https://man.openbsd.org/tmux
- iTerm2 Documentation: https://iterm2.com/documentation.html