Git Worktrees Tutorial
Master Git Worktrees: A Comprehensive Guide to Multi-Branch Development
Git Worktrees Tutorial
What Are Git Worktrees?
Git worktrees allow you to check out multiple branches from the same repository into different directories simultaneously. Instead of constantly switching branches with git checkout, you can have multiple branches checked out at once, each in its own directory.
Why Use Worktrees?
- Parallel work: Work on multiple features or bug fixes simultaneously without switching contexts
- Code comparison: Easily compare implementations across branches
- Testing: Test one branch while developing another
- Isolated environments: Each worktree has its own dependencies, build artifacts, and running processes
- No stashing: No need to stash changes when switching between tasks
Basic Commands
Create a Worktree
# Create a new worktree with a new branch
git worktree add <path> -b <branch-name>
# Example: create a worktree for a new feature
git worktree add ../my-feature -b feature/authentication
Create a Worktree from Existing Branch
# Check out an existing branch in a new worktree
git worktree add <path> <existing-branch>
# Example: check out main branch in a separate directory
git worktree add ../main-worktree main
List All Worktrees
git worktree list
Example output:
/Users/dev/myproject 2ca8c70 [main]
/Users/dev/my-feature a1b2c3d [feature/authentication]
/Users/dev/bugfix e4f5g6h [bugfix/validation-error]
Remove a Worktree
# Remove a worktree (must be run from main repository)
git worktree remove <path>
# Example
git worktree remove ../my-feature
Clean Up Deleted Worktrees
# Remove worktree administrative files for deleted directories
git worktree prune
Recommended Directory Structure
Project-Local (Recommended)
Keep worktrees within your project using a dedicated directory:
myproject/
├── .git/
├── .gitignore # Add .worktrees/ here
├── .worktrees/ # Hidden directory for worktrees
│ ├── feature-auth/
│ ├── bugfix-123/
│ └── experiment/
├── src/
└── package.json
Important: Add .worktrees/ to your .gitignore to prevent accidentally committing worktree contents:
echo ".worktrees/" >> .gitignore
git add .gitignore
git commit -m "Add worktrees directory to gitignore"
Sibling Directories
Create worktrees as siblings to your main project:
workspace/
├── myproject/ # Main repository
├── myproject-feature1/ # Worktree 1
└── myproject-feature2/ # Worktree 2
Complete Workflow Example
Let’s walk through a real-world scenario:
Scenario: You’re working on a feature when an urgent bug needs fixing
1. Check current status
cd ~/projects/myapp
git status
# On branch feature/new-dashboard
# Changes not staged for commit: ...
2. Create a worktree for the bugfix
git worktree add .worktrees/hotfix -b hotfix/critical-bug
cd .worktrees/hotfix
3. Install dependencies (if needed)
npm install
# or pip install -r requirements.txt
# or cargo build
4. Fix the bug
# Make your changes
git add .
git commit -m "Fix critical validation bug"
git push origin hotfix/critical-bug
5. Return to feature work
cd ../.. # Back to main repository
# Your feature work is exactly as you left it
6. Clean up when done
git worktree remove .worktrees/hotfix
Setting Up Dependencies in Worktrees
Each worktree is a complete working directory, so you need to set up dependencies:
Node.js
cd .worktrees/my-feature
npm install
Python
cd .worktrees/my-feature
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Rust
cd .worktrees/my-feature
cargo build
Go
cd .worktrees/my-feature
go mod download
Advanced Usage
Create Worktree from Remote Branch
# Fetch the remote branch first
git fetch origin feature/remote-work
# Create worktree from remote branch
git worktree add .worktrees/remote-feature origin/feature/remote-work
Move a Worktree
# Move the directory
mv .worktrees/old-name .worktrees/new-name
# Update git's records
git worktree move .worktrees/old-name .worktrees/new-name
Lock a Worktree
Prevent a worktree from being pruned:
git worktree lock .worktrees/important-feature --reason "Long-term experiment"
Unlock it later:
git worktree unlock .worktrees/important-feature
Best Practices
1. Use Consistent Naming
Choose a naming convention and stick to it:
.worktrees/feature-<name>.worktrees/bugfix-<issue-number>.worktrees/experiment-<description>
2. Always Add Worktree Directory to .gitignore
echo ".worktrees/" >> .gitignore
This prevents accidentally committing worktree contents to your repository.
3. Clean Up Regularly
Remove worktrees when you’re done:
git worktree list
git worktree remove <path>
git worktree prune
4. Verify Clean Baseline
Before starting work in a new worktree, run tests to ensure you’re starting from a clean state:
cd .worktrees/new-feature
npm test # or your project's test command
5. Share Worktree Setup in Documentation
If your team uses worktrees, document the preferred directory structure in your project’s README or CONTRIBUTING guide.
Common Mistakes to Avoid
1. Forgetting to Add Worktree Directory to .gitignore
Problem: Worktree contents appear in git status of main repository
Solution: Always add your worktree directory to .gitignore
2. Deleting Worktree Directory Manually
Problem: Git still tracks the worktree, causing confusion
Solution: Always use git worktree remove instead of rm -rf
3. Not Installing Dependencies
Problem: Code doesn’t run in the new worktree
Solution: Run your project’s setup commands (npm install, pip install, etc.) in each new worktree
4. Working on Same Branch in Multiple Worktrees
Problem: Git won’t allow you to check out the same branch in multiple worktrees
Solution: Each worktree must use a different branch
Troubleshooting
”Branch X is already checked out”
You can’t check out the same branch in multiple worktrees. Create a new branch or use a different existing branch.
Worktree is Gone but Git Still Tracks It
# If you manually deleted a worktree directory
git worktree prune
Can’t Remove Worktree
# Check if it's locked
git worktree list
# If locked, unlock it first
git worktree unlock <path>
# Then remove
git worktree remove <path>
Need to Find All Worktrees
# List all worktrees with detailed information
git worktree list --porcelain
Quick Reference
| Task | Command |
|---|---|
| Create worktree with new branch | git worktree add <path> -b <branch> |
| Create worktree from existing branch | git worktree add <path> <branch> |
| List all worktrees | git worktree list |
| Remove worktree | git worktree remove <path> |
| Clean up deleted worktrees | git worktree prune |
| Move worktree | git worktree move <old-path> <new-path> |
| Lock worktree | git worktree lock <path> |
| Unlock worktree | git worktree unlock <path> |
Conclusion
Git worktrees are a powerful feature for managing multiple tasks simultaneously. They eliminate the need for branch switching, reduce context switching overhead, and provide isolated environments for each task. Once you incorporate worktrees into your workflow, you’ll wonder how you ever managed without them.