Git Worktree: Parallel Branch Development
💡 In one sentence:
git worktreelets you check out multiple branches from the same repository at once. Switching is justcd—no stash required.
What You'll Learn
- Switch to another branch for urgent work without interrupting your current task
- Develop multiple feature branches at the same time without interference
- Switch workspaces quickly with OpenCode's
/workspaces - Understand how worktrees differ from stash and clone, and choose the right approach
The Problem
You are halfway through a feature on feature/new-api. Suddenly:
- Production has a bug and you need to switch to
hotfix - A teammate sends you a PR that you need to run locally
- You want to compare an implementation detail with an older version
The traditional approach:
git stash # Stash current changes
git checkout hotfix # Switch branches
# ... fix the bug ...
git checkout feature # Switch back
git stash pop # Restore changes (and possibly hit conflicts!)Problems:
- A stash can conflict
- You lose context and pay the mental cost of restoring it
- Every switch requires rebuilding your working state
When to Use This
- When you need to work on tasks across multiple branches at once
- And you do not want to keep stashing, switching, and restoring
🎒 Prerequisites
Make sure you have completed the following:
- [ ] Understand basic Git branch operations
- [ ] Git 2.5 or later (released in 2015, so nearly every installation qualifies)
git --version
# git version 2.43.0 (ok)Core Concepts
What Is Git Worktree?
Git Worktree, introduced in Git 2.5, allows a single repository to have multiple working directories, each with a different branch checked out.
# Traditional: one directory can have only one branch checked out at a time
my-project/ ← main or feature, but not both
# Worktrees: multiple directories and branches in parallel
my-project/ ← main branch
my-project-hotfix/ ← hotfix branch (independent directory)
my-project-review/ ← PR branch (independent directory)Why Is It Better Than the Alternatives?
| Comparison | git stash | git clone | git worktree |
|---|---|---|---|
| Disk usage | None | High (full copy) | Low (shared .git) |
| Parallel branches | ❌ Sequential | ✅ Parallel | ✅ Parallel |
| Context retained | ❌ Lost | ✅ Independent | ✅ Independent |
| Synchronization cost | None | High (fetch separately) | Low (shared data) |
| Best for | Brief switches lasting minutes | Complete isolation | Long-running parallel development |
How It Works
When you run git worktree add ../hotfix hotfix-branch:
- Create a directory:
../hotfix/ - Check out the branch: place the files from
hotfix-branchin that directory - Create a link:
.gitin the new directory is a file that points to the main repository
# .git is a directory in the main repository
ls -la project/.git
drwxr-xr-x .git/
# .git is a file in a worktree
ls -la ../hotfix/.git
-rw-r--r-- .git # Contents: gitdir: /path/to/project/.git/worktrees/hotfixAll worktrees share one Git object database:
- A commit made in any worktree is immediately visible to the others
- Run
git fetchonce and every worktree is updated
Follow Along
Step 1: Inspect the Current Worktrees
Why To understand the repository's current working-tree state.
cd your-project
git worktree listYou should see:
/path/to/your-project abc1234 [main]One line means there is only the default working directory.
Step 2: Create a Worktree
Why To work on another branch without disturbing your current work.
Suppose you are on main and need to fix a bug on hotfix/login:
# Syntax: git worktree add <path> <branch>
git worktree add ../my-project-hotfix hotfix/loginYou should see:
Preparing worktree (checking out 'hotfix/login')
HEAD is now at abc1234 Fix login validationRecommended directory layout
Put worktrees in a sibling directory (../project-branch), not inside the project.
❌ Avoid: git worktree add ./hotfix ✅ Recommended: git worktree add ../my-project-hotfix
Step 3: Work in the Worktree
Why To use an independent development environment without interference.
# Switch to the new directory
cd ../my-project-hotfix
# You are now on hotfix/login
git branch
# * hotfix/login
# Develop and commit as usual
git add .
git commit -m "Fix login validation bug"
git pushMeanwhile, the original directory remains untouched:
cd ../your-project
git status
# Still in its previous state, including every uncommitted changeStep 4: List All Worktrees
Why To verify your working-tree list.
git worktree listYou should see:
/path/to/your-project abc1234 [main]
/path/to/my-project-hotfix def5678 [hotfix/login]Step 5: Remove a Worktree
Why To clean up after the task and prevent worktrees from accumulating.
# Return to the main directory
cd /path/to/your-project
# Remove the worktree
git worktree remove ../my-project-hotfixYou should see: the directory is removed and only one line remains in the worktree list.
If it contains uncommitted changes, force removal:
git worktree remove --force ../my-project-hotfixStep 6: Use Workspaces in OpenCode
Why To switch quickly from the TUI with OpenCode's experimental workspace feature. In v1.18.22, workspaces use an adapter architecture and the built-in adapter is worktree. /workspaces manages workspaces created or discovered by adapters; it is not a separate cloning mechanism.
First, enable the experimental feature:
# Add to ~/.zshrc or ~/.bashrc
export OPENCODE_EXPERIMENTAL_WORKSPACES=1
# Reload the file
source ~/.zshrcRestart opencode and enter:
/workspacesYou should see: a workspace dialog listing the current project and every worktree.
| Action | Description |
|---|---|
| Select a workspace | Switch to that worktree directory |
| + New workspace | Create a new worktree |
| Press Delete | Remove the selected worktree |
Current implementation versus historical releases
The v1.16.0 release introduced managed workspace cloning and advertised preservation of dirty and untracked files. By v1.18.22, creation and discovery use the workspace adapter architecture with the built-in worktree adapter. When moving a session, copyChanges can copy a Git patch, but that does not mean all historical managed-clone behavior remains available. In particular, do not promise that untracked files will be copied.
Current implementation:
adapters/index.ts:5-18,adapters/worktree.ts:28-95,workspace.ts:559-620, andworkspace.ts:728-739. Historical evidence: thev1.16.0release and commit5661af203487b90cf9ee0844b198b03cce26c412.
Checklist ✅
- [ ] Understand what a worktree is and why it can be better than stash or clone
- [ ] Can create a worktree with
git worktree add - [ ] Can list worktrees with
git worktree list - [ ] Can remove a worktree with
git worktree remove - [ ] Enabled OpenCode workspaces and can switch with
/workspaces
Advanced: Best Practices
1. Bare Repository Pattern
If you regularly maintain several worktrees, use the bare repository pattern:
# Clone as a bare repository (no working tree)
git clone --bare [email protected]:user/repo.git repo.git
cd repo.git
# Create worktrees (using branch names as directory names)
git worktree add main main
git worktree add ../feature feature-branch
git worktree add ../hotfix hotfix-branchDirectory structure:
code/
├── repo.git/ # Bare repository (.git data only)
│ └── main/ # worktree: main branch
├── feature/ # worktree: feature branch
└── hotfix/ # worktree: hotfix branchAdvantages:
- Every branch is equal; there is no primary or secondary worktree
- The directory structure is clear: branch name = directory name
- One
fetchupdates every worktree
2. Naming Conventions
| Style | Example | Use Case |
|---|---|---|
| Project-branch | my-project-hotfix | Temporary worktree |
| Branch name directly | feature/login | Bare repository pattern |
| Project + purpose | my-project-review | Dedicated PR review worktree |
3. Clean Up Regularly
Build the habit of removing a worktree immediately after its branch is merged.
# Remove the worktree for a merged branch
git worktree remove ../feature-done
git branch -d feature-done
# Remove orphaned records (for example, after manually running rm -rf on a directory)
git worktree prune4. Use It with an IDE
Each worktree can be opened as an independent project:
# VS Code
code ../my-project-hotfix
# IntelliJ
# Open → select the directoryEach branch then has independent:
- Run configurations
- Breakpoints
- Open files
Common Pitfalls
⚠️ One Branch Cannot Be Checked Out Twice
# Suppose main is already checked out in the primary directory
git worktree add ../another-main main
# fatal: 'main' is already checked out at '/path/to/project'Solution: create a new branch.
git worktree add -b hotfix/from-main ../hotfix main⚠️ Do Not Put Worktree Directories Inside the Project
# ❌ Wrong: creates the directory inside the project
git worktree add ./hotfix branch-name
# ✅ Correct: use a sibling directory
git worktree add ../project-hotfix branch-namePutting it inside causes:
- Confusing Git ignore behavior
- Incorrect paths in tooling scripts
- The mental mismatch that it “doesn't belong to this project”
⚠️ node_modules Is Duplicated
Every worktree is an independent working directory, so dependencies must be installed separately:
cd ../project-hotfix
npm install # or pnpm installFor large projects, this is the main time cost.
Mitigations:
- Use pnpm's global store, which saves space through hard links
- Configure a shared cache directory
⚠️ stash Is Global
All worktrees share one stash list:
# Stash in worktree A
git stash push -m "WIP feature"
# See it from worktree B
git stash listThis can become confusing. Recommendation: if you use worktrees, avoid stash.
Real-World Scenarios
Scenario 1: Urgent Bug Fix
You are developing feature/new-api
→ Product: “Production is down!”
→ git worktree add ../hotfix hotfix/urgent
→ cd ../hotfix, fix, deploy
→ cd ../feature, continue developingScenario 2: PR Review
Teammate: “Can you review this PR?”
→ git fetch origin
→ git worktree add ../review origin/their-branch
→ cd ../review, run tests, inspect code
→ Finish the review and remove the worktreeScenario 3: Parallel Comparison Testing
You want to compare old and new implementations
→ git worktree add ../old-version v1.0.0
→ git worktree add ../new-version v2.0.0
→ Run both directories simultaneously and compare the resultsCommand Cheat Sheet
| Command | Purpose |
|---|---|
git worktree add <path> <branch> | Create a worktree |
git worktree add -b <new-branch> <path> | Create a new branch and worktree |
git worktree list | List all worktrees |
git worktree remove <path> | Remove a worktree |
git worktree remove --force <path> | Force removal when uncommitted changes exist |
git worktree prune | Remove orphaned records |
git worktree lock <path> | Lock a worktree to prevent accidental removal |
git worktree move <path> <new-path> | Move a worktree |
Lesson Summary
| Concept | Key Point |
|---|---|
| What it is | One repository, multiple working directories, shared .git data |
| What it solves | Expensive branch switching, stash risk, and wasted disk space from clones |
| When to use it | Urgent fixes, parallel development, PR reviews, and comparison testing |
| Best practices | Bare repository pattern, consistent naming, and regular cleanup |
| OpenCode integration | Switch quickly with /workspaces |
Next Lesson
Next, we'll cover the Experimental Features Overview.
You'll learn:
- The complete list of experimental features
- Which features to enable as needed
- Environment-variable configuration techniques
Appendix: Source Code Reference
Click to expand source code locations
Target version: v1.18.22 (2026-08-24)
| Feature | File Path | Lines |
|---|---|---|
| Adapter registration (built-in worktree) | src/control-plane/adapters/index.ts | 5-18 |
| Worktree adapter | src/control-plane/adapters/worktree.ts | 28-95 |
| Workspace creation | src/control-plane/workspace.ts | 492-538 |
| Adapter discovery and registration | src/control-plane/workspace.ts | 728-739 |
| Workspace-aware routing | workspace-routing.ts | 148-185 |
| Experimental switch | src/effect/runtime-flags.ts | 43-50 |
TUI /workspaces command | packages/tui/src/app.tsx | 610-618 |
Key environment variable:
OPENCODE_EXPERIMENTAL_WORKSPACES=1: enable TUI workspace support

