Git Worktree — Simultaneous Branches Without Stashing Chaos
Stop stashing and switching.
20+ years shipping production infrastructure and CI/CD at scale. Everything here is grounded in real deployments.
- ✓Git 2.5+ (worktree feature introduced), Bash shell, basic Git commands (clone, branch, checkout, commit, push), understanding of Git branches and remotes, familiarity with command-line navigation
git worktree add ../project-hotfix hotfix/bug creates a new directory with the hotfix branch checked out. git worktree list shows all worktrees. git worktree remove ../project-hotfix cleans up.
Imagine having the same book open to two different chapters at the same time on your desk. git worktree is like having two physical copies of the repo on your hard drive, but they share the same bookmark file (.git). You can work on a feature in one window and review a PR in another, without stashing or committing half-done work.
The standard Git workflow forces you to stash or commit before switching branches. git worktree removes this constraint entirely. Each worktree is a full working directory linked to the same .git database. You can build and test both branches simultaneously, switch between them instantly, and never lose context. The one constraint: a branch can only be checked out in one worktree at a time. This guide covers setup, the constraint that caught a team mid-deploy, and how to integrate worktrees into your daily workflow.
Why Git Worktree Exists
Git worktree allows you to check out multiple branches of the same repository into separate working directories. This solves a fundamental pain: context switching. Instead of stashing or committing half-baked changes to switch branches, you keep each branch in its own directory. No more 'I need to hotfix master but I'm in the middle of a feature' panic. Worktrees share the same Git object store, so disk usage is minimal. They are not clones—they are linked to the original repository. This means you can work on a feature, review a PR, and debug a production issue simultaneously without losing your place. The primary use case is parallel development, but it also shines for CI/CD testing, code review, and long-running experiments. Senior devs use worktrees to avoid the overhead of multiple clones and to keep their main working tree clean. If you're still using git stash for context switching, you're wasting time.
Creating and Managing Worktrees
Creating a worktree is simple: git worktree add <path> <branch>. If the branch doesn't exist, add -b to create it. The path is relative or absolute. Once created, you can cd into that directory and work normally. To list all worktrees: git worktree list. To remove a worktree: git worktree remove <path>. Always clean up worktrees when done—they are not automatically deleted. A common mistake is trying to delete a branch that has an active worktree. Git will refuse. You must remove the worktree first. Also, you cannot have two worktrees on the same branch. If you need multiple copies of the same branch, use git clone instead. Worktrees are tied to the parent repo's HEAD; if you delete the parent repo, worktrees become orphaned. Always remove worktrees before deleting the parent. For CI pipelines, worktrees can be used to run tests in parallel on different branches without cloning the repo multiple times.
add, list, and remove. They are lightweight but require explicit cleanup.Worktree Internals: How They Share Objects
Worktrees share the Git object store (.git/objects) with the parent repository. Each worktree has its own .git file pointing to the parent's .git directory. This means all objects (commits, trees, blobs) are stored once. The worktree's HEAD, index, and refs are separate. When you commit in a worktree, new objects are added to the shared store. This is efficient: a 1GB repo with 10 worktrees still uses ~1GB, not 10GB. However, there are pitfalls. Git operations like git gc run on the parent repo and affect all worktrees. If a worktree has unreachable objects, they won't be pruned because the worktree's reflog protects them. Also, git prune can be dangerous if worktrees are active. Always use git gc --auto which respects worktrees. Another internal detail: worktrees use a separate ref namespace under refs/worktrees/. This prevents conflicts. Understanding this helps debug issues like 'fatal: refusing to merge unrelated histories' when a worktree's branch diverges.
git prune in a worktree thinking it would clean only that worktree. It pruned objects needed by the parent repo, causing corruption. Always run GC from the parent repo.Parallel Feature Development with Worktrees
The most common use case: working on two features simultaneously. Create a worktree for each feature branch. You can switch between directories without stashing. Each worktree has its own node_modules, build artifacts, etc. This is especially useful for monorepos where building takes time. You can have one worktree building while you code in another. No more waiting for a build to finish to switch branches. However, beware of shared resources like databases or ports. If both worktrees run the same server, they'll conflict. Use environment variables or Docker to isolate. Also, if you use an IDE, each worktree can have its own window. This avoids IDE reloading when switching branches. For code review, you can check out a PR branch into a worktree, review, and delete it—all without touching your main worktree. This keeps your primary workspace clean. Senior devs often have a 'main' worktree for daily work and temporary worktrees for reviews or experiments.
Hotfixes Without Disruption
Production incidents require immediate attention. With worktrees, you can create a hotfix worktree from the production branch (e.g., master) without touching your feature branch. No stash, no partial commits. Just git worktree add ../hotfix master, fix the bug, commit, push, and deploy. Then remove the worktree. Your feature branch remains untouched. This is a lifesaver when you have uncommitted changes or a broken working tree. The hotfix worktree is clean because it's based on master. You can even have multiple hotfix worktrees for different incidents. The key is to name them descriptively (e.g., hotfix-CVE-2024-1234). After deployment, delete the worktree and the branch. This workflow is faster than cloning the repo again, especially for large repos. It also avoids the risk of accidentally deploying feature code with the hotfix.
CI/CD and Testing with Worktrees
Worktrees are excellent for CI/CD pipelines. Instead of cloning the repo for each job, you can create worktrees from a bare clone. This reduces network transfer and disk usage. For example, in a Jenkins pipeline, you can have a bare repo on the agent, then create worktrees for each branch being tested. After tests, remove the worktree. This is faster than git clone --depth 1 because objects are already local. However, be careful with concurrent access. If multiple jobs create worktrees from the same bare repo, Git handles it fine as long as branches are different. For the same branch, you need to use git worktree add --detach to avoid conflicts. Also, ensure cleanup in post or finally blocks to avoid leftover worktrees. Another use case: running integration tests against multiple versions of a dependency. Create worktrees for each version branch and run tests in parallel.
Common Pitfalls and How to Avoid Them
Worktrees have sharp edges. First, you cannot delete a branch that has an active worktree. Git will error: 'Cannot delete branch checked out at ...'. Remove the worktree first. Second, worktrees are not automatically cleaned when you delete the parent repo. They become orphaned. Always remove worktrees before deleting the parent. Third, git gc in the parent repo may prune objects that worktrees still need. Git protects worktrees' reflogs, but if a worktree is detached or has been removed improperly, objects can be lost. Fourth, worktrees on the same branch cause conflicts. Use --detach if you need multiple worktrees on the same commit. Fifth, moving or renaming worktrees manually breaks the .git pointer. Always use git worktree move or git worktree remove and re-add. Sixth, worktrees with submodules require extra care. Submodules are shared but their working trees are independent. You may need to run git submodule update in each worktree.
git worktree move instead.Advanced: Worktrees with Submodules and Large Repos
Worktrees and submodules interact in subtle ways. When you create a worktree, submodules are not automatically cloned. You must run git submodule update --init --recursive in each worktree. The submodules themselves are shared via the parent's .git/modules, but each worktree has its own submodule working tree. This can lead to confusion if you update a submodule in one worktree—the changes are visible in the parent's submodule cache but not in other worktrees until they update. For large repos (e.g., monorepos with gigabytes of history), worktrees are a blessing. They avoid cloning the entire history multiple times. However, git worktree add can be slow for huge repos because it needs to checkout the branch. Use --no-checkout and then git checkout manually to speed it up. Also, consider using sparse checkout in worktrees to reduce disk usage. For example, git sparse-checkout set /path/to/subdir in a worktree limits the working tree to a subset of files.
Worktree Workflow for Code Review
Code review often requires checking out a branch to test changes. Instead of stashing your current work, create a worktree for the review branch. After review, remove the worktree. This keeps your main working tree clean. For GitHub or GitLab, you can fetch the PR branch and add a worktree. For example: git fetch origin pull/123/head:pr-123 && git worktree add ../pr-123 pr-123. Review, test, then remove. You can even have multiple PR worktrees simultaneously. This is especially useful for reviewers who need to test multiple PRs in parallel. Some teams automate this with scripts that create worktrees for each open PR. The key is to name worktrees after the PR number for easy identification. After merging, delete the worktree and the local branch. This workflow is faster than using git stash and avoids the risk of losing changes.
Cleaning Up: Best Practices for Worktree Hygiene
Worktrees are powerful but can clutter your filesystem if not managed. Establish a naming convention: ../hotfix-<ticket>, ../feature-<ticket>, ../review-pr-<number>. Always remove worktrees when done. Use git worktree prune to clean up stale worktree references (e.g., if a worktree directory was deleted manually). This command removes the metadata from .git/worktrees. However, it does not delete the actual directory—you must do that separately. For CI, always include cleanup in a finally block. For local development, periodically run git worktree list and remove unused ones. Consider using a script that lists worktrees older than a certain age and prompts for removal. Also, avoid creating worktrees inside the parent repo's directory—use sibling directories. This prevents confusion and accidental deletion. Finally, educate your team: worktrees are not clones; they are linked. Deleting the parent repo without removing worktrees first causes orphaned directories.
git worktree prune only cleans metadata. You must delete the worktree directory separately.When Not to Use Worktrees
Worktrees are not a silver bullet. Avoid them when: 1) You need to work on the same branch simultaneously from different machines. Use a clone instead. 2) You need to run the same application with different configurations on the same machine. Worktrees share the same filesystem, so config files might conflict. Use Docker or environment variables. 3) You are working with a repo that has a huge number of refs (e.g., 10,000+ branches). git worktree add can be slow because it enumerates refs. Consider using --no-checkout. 4) You are on a filesystem with slow metadata operations (e.g., NFS). Worktrees create many symlinks and files, which can be slow. 5) You need to delete the parent repo frequently. Worktrees become orphaned. Instead, use clones. 6) You are using a Git GUI that doesn't support worktrees. Some tools may not recognize worktrees. Stick to CLI. 7) You are working with submodules that have their own submodules. The complexity increases. Evaluate if the benefit outweighs the overhead.
git worktree add took 2 minutes. We switched to local SSD and it dropped to 2 seconds.Integrating Worktrees into Your Daily Workflow
To adopt worktrees effectively, integrate them into your daily routine. Start by creating a worktree for your main feature branch. Then, when a hotfix or review comes up, create a temporary worktree. After finishing, remove it. Over time, you'll develop muscle memory. Use shell aliases to speed up common operations: alias gwa='git worktree add', alias gwl='git worktree list', alias gwr='git worktree remove'. For teams, document the workflow in your onboarding guide. Include a script that sets up a standard worktree structure. For example, a script that creates worktrees for all branches you commonly work on. Also, consider using a tool like git-worktree-manager (a simple bash script) to manage worktrees. The key is consistency: always name worktrees descriptively and clean up promptly. With practice, worktrees become second nature and you'll wonder how you lived without them.
The Deploy That Failed Because a Branch Was Locked
git worktree add ../deploy-prep main to prepare a deployment. 2. They forgot to remove the worktree after finishing. 3. The branch 'main' was locked by the worktree — Git prevents writes to a branch that's checked out anywhere. 4. The CI pipeline's git fetch failed because it couldn't update the remote-tracking ref for main. 5. The error message ('refusing to fetch into checked out branch') was confusing because main wasn't checked out in the CI runner — it was checked out in the developer's worktree on a different machine.git worktree list on the developer's machine. 2. The worktree was stale (the directory had been deleted but Git didn't know). 3. Ran git worktree prune to remove stale worktree records. 4. Re-ran the CI pipeline successfully. 5. Added a pre-deploy CI check: git worktree list should show only the CI runner's worktree.- Worktrees lock branches.
- A branch can only be checked out in ONE worktree at a time.
- Always run
git worktree pruneregularly and clean up worktrees when done. - CI pipelines should check for stale locks before deploying.
git worktree add ../review-branch <branch-name> — creates a new directory with the PR branchgit worktree add ../hotfix -b hotfix/critical — starts a new branch in a separate directorygit worktree list then git worktree remove <path> for each one you don't need| File | Command / Code | Purpose |
|---|---|---|
| create-worktree.sh | cd /path/to/repo | Why Git Worktree Exists |
| manage-worktrees.sh | git worktree list | Creating and Managing Worktrees |
| inspect-worktree.sh | cat /path/to/hotfix/.git | Worktree Internals |
| parallel-features.sh | cd /path/to/repo | Parallel Feature Development with Worktrees |
| hotfix-workflow.sh | cd /path/to/repo | Hotfixes Without Disruption |
| ci-worktree.sh | cd /path/to/bare-repo.git | CI/CD and Testing with Worktrees |
| pitfalls.sh | git branch -D hotfix-branch | Common Pitfalls and How to Avoid Them |
| submodule-worktree.sh | cd /path/to/repo | Advanced |
| review-worktree.sh | cd /path/to/repo | Worktree Workflow for Code Review |
| cleanup.sh | git worktree list | Cleaning Up |
| when-not-to.sh | time git worktree add ../test feature | When Not to Use Worktrees |
| aliases.sh | alias gwa='git worktree add' | Integrating Worktrees into Your Daily Workflow |
Key takeaways
git worktree pruneFrequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Everything here is grounded in real deployments.
That's Git. Mark it forged?
7 min read · try the examples if you haven't