Switching branches in the middle of a task is annoying. You stash, you checkout, you fix the thing, you checkout back, you pop the stash and hope. Git worktrees remove that whole loop, and since AI coding agents arrived they have become the standard way to run several of them at once without collisions.
I touched on worktrees in my post on git tricks that save my day. This is the full version.
What is a git worktree?
A git worktree is an extra working directory linked to the same repository. Each worktree has its own checked-out branch, files and index, but they all share one .git history, so commits, branches and remotes are visible everywhere. You can work on two branches at the same time, in two folders, with no stashing.
The main checkout you cloned is the main worktree. Every extra one is a linked worktree. The official manual describes the linked worktree as sharing the repository with the main one, except for per-worktree files such as HEAD and index.
How do you use git worktree? Commands reference
This is the synopsis from the git-worktree manual, trimmed to what you use day to day.
| Command | What it does |
|---|---|
git worktree add <path> [<commit-ish>] | Create a linked worktree at the path and check out the commit-ish |
git worktree list | Show the main worktree first, then each linked one |
git worktree remove <worktree> | Delete a linked worktree directory and its admin data |
git worktree prune | Clear admin data for worktrees whose directories are gone |
git worktree move <worktree> <new-path> | Move a linked worktree to a new location |
git worktree lock <worktree> | Protect a worktree from pruning, moving or deleting |
git worktree unlock <worktree> | Undo a lock |
git worktree repair | Fix links that broke after you moved a directory by hand |
git worktree add
git worktree add ../project-hotfix hotfix/login-bug
git worktree add -b feature-x ../project-feature-x main
git worktree add -d ../scratchThe first line checks out an existing branch in a new folder. The second creates a new branch feature-x from main. The third creates a worktree with a detached HEAD, which is handy for throwaway experiments.
Useful add options from the manual:
| Option | Effect |
|---|---|
-b <new-branch> | Create a branch. Refuses if it already exists. |
-B <new-branch> | Create the branch, or reset it to the commit-ish if it exists |
-d, --detach | Detached HEAD |
--orphan | Empty worktree and index on a new unborn branch |
--lock | Lock the worktree at creation (add --reason for a note) |
--no-checkout | Skip checkout, for example to set up sparse-checkout first |
--track, --no-track | Control upstream tracking when creating a branch |
If you leave out the commit-ish and pass no -b, -B or --detach, git names the new branch after the basename of the path, creating it from HEAD if it does not exist. There is also remote-branch guessing: if the name matches a remote-tracking branch on exactly one remote, git treats the command as add --track -b against that remote.
git worktree list
git worktree listOutput shows the path, the short commit hash and the branch, with annotations such as locked and prunable. Use -v to see lock reasons. For scripts, use git worktree list --porcelain, which the manual says has a stable format across git versions (add -z for NUL-terminated lines if paths could contain newlines).
git worktree remove and prune
git worktree remove ../project-hotfix
git worktree remove --force ../project-hotfix
git worktree prune -vremove only works on a clean worktree (no untracked files, no modified tracked files) unless you pass --force. The main worktree cannot be removed. A locked worktree needs --force twice.
If you delete a worktree folder with rm -rf instead, git keeps its admin data in $GIT_DIR/worktrees. It cleans that up automatically after gc.worktreePruneExpire, or right away with git worktree prune. Use git worktree prune -n for a dry run and --expire to only prune entries older than a given time.
git worktree move, lock and repair
git worktree move ../project-hotfix ../hotfix
git worktree lock --reason "on external drive" ../project-hotfix
git worktree repairLock is for worktrees on storage that is not always mounted, such as a USB drive or network share, so a prune does not wipe their admin data. move cannot move the main worktree or a linked worktree that contains submodules. If you moved a directory manually, repair fixes the broken links. Run it inside the moved worktree, or pass the new paths from anywhere.
Git worktree vs branch vs stash
These three solve related problems and people mix them up. A branch is a pointer to commits. A worktree is a folder where a branch is checked out. A stash is a shelf for uncommitted changes.
| Branch | Worktree | Stash | |
|---|---|---|---|
| What it is | A named pointer to a commit | A separate working directory | Saved uncommitted changes |
| Needs a checkout | Yes, one per working directory | It provides one | No |
| Two active at once | Not in one folder | Yes, one per folder | Not applicable |
| Keeps uncommitted work | No, you carry it or stash it | Yes, in its own folder | Yes, until popped |
| Disk cost | Almost none | A full set of files | Almost none |
| Best for | Organizing history | Parallel tasks, hotfixes, agents | Quick context switch |
So "git worktree vs branch" is not either/or. You still need a branch for every worktree (or a detached HEAD). The worktree is what lets two branches be checked out at once. Use a stash when you have a ten-second interruption. Use a worktree when the interruption will take a while, or when you want two long-running tasks side by side.
Git worktree gotchas
You cannot check out the same branch twice. git worktree add refuses when the branch is already checked out in another worktree. --force overrides the safeguard, but I would not: two folders writing to one branch is how you lose commits. Make a new branch instead.
Dependencies are not shared. A worktree is a fresh checkout. node_modules, build output and virtualenvs are untracked, so they are not there. Run your install command in each worktree.
Untracked config is not copied. Your .env and .env.local are gitignored, so they do not appear in the new worktree. Copy them over, or script it.
Ports and databases collide. Two dev servers on port 3000 will fight. Give each worktree its own port and, if you use a local database, its own database name.
Submodules are rough. The manual says multiple checkout is still experimental, submodule support is incomplete, and it does not recommend making multiple checkouts of a superproject. remove needs --force for worktrees with submodules, and move does not work on them.
Shared and per-worktree state. Branches and tags (refs/heads/*, refs/tags/*) are shared. HEAD and the index are per worktree. So are refs/bisect/*, which means you can bisect in one worktree without disturbing another.
Config is shared by default. The repo config file applies to all worktrees. If you need per-worktree settings, such as core.sparseCheckout, enable extensions.worktreeConfig and use git config --worktree. Older git versions refuse to open repositories that use that extension.
Do not delete the folder by hand. Use git worktree remove. If you did delete it, run git worktree prune.
Does Claude Code have a worktree feature?
Yes. Claude Code has a built-in --worktree flag (short form -w). According to the Claude Code worktree docs, it creates an isolated worktree and starts the session in it:
claude --worktree feature-authDefaults from the docs:
- The worktree is created under
.claude/worktrees/<name>/at the repo root, on a new branch namedworktree-<name>. - If you omit the name, Claude generates one (the docs give
bright-running-foxas an example). - New worktrees branch from the repository's default branch on the remote (
worktree.baseRefis"fresh"by default). Setworktree.baseRefto"head"in settings to branch from your current localHEADinstead. - The repository needs at least one commit first.
- The docs suggest adding
.claude/worktrees/to.gitignore.
You can also ask Claude mid-session to "work in a worktree" and it uses its EnterWorktree tool. You can pass a pull request to --worktree (for example claude --worktree "#1234") and it fetches that PR's head into .claude/worktrees/pr-<number>.
Two details solve gotchas from the previous section. A .worktreeinclude file at the project root, in .gitignore syntax, lists gitignored files (like .env) that Claude copies into each new worktree it creates. Dependencies are still on you: the docs tell you to install them in the new worktree, or ask Claude to.
On exit, Claude checks the worktree. A clean unnamed session removes the worktree and branch automatically. If there is work in it, Claude asks whether to keep or remove it.
If you prefer plain git, that works too, and the docs show it: git worktree add ../project-feature-a -b feature-a, then cd in and run claude.
How do you run parallel AI agents with git worktrees?
The pattern is one worktree per agent session, each on its own branch. The agents cannot overwrite each other's files because they are in different folders. You review and merge branches like any other.
A workflow that works with Claude Code:
- Pick tasks that touch different files. Parallel agents on the same file still produce merge conflicts.
- Start a session per task in its own worktree:
claude --worktree fix-login-bug- In a second terminal, start another:
claude --worktree add-export-csv- Let each agent work, run tests and commit on its own branch.
- Review each branch as a normal pull request.
- Remove the worktrees you no longer need with
git worktree remove, or accept Claude's prompt on exit.
The Claude Code docs also cover subagents running in their own worktrees. Ask Claude to "use worktrees for your agents", or set isolation: worktree in a custom subagent's frontmatter. Each subagent gets a temporary worktree that is removed automatically if it finishes without changes.
Worktrees isolate file edits only. They do not isolate your machine. Agents still share ports, databases and anything outside the checkout, and the docs note that a shell command like cp writing into the main checkout is not blocked by the worktree checks. Treat permissions as a separate problem, which I cover in coding agent permissions and least privilege.
For the bigger picture on agents that run unattended, see background AI coding agents. If you run several sessions, a status line that shows the model, context and branch helps you tell them apart. I wrote a Claude Code status line guide for that.
When should you not use a worktree?
- The task is a two-minute detour. A stash is faster.
- The repo is huge and a second full checkout is expensive on disk or install time.
- The project uses submodules heavily, given the manual's warnings.
- Your parallel tasks all touch the same files. You will pay the setup cost and still hit conflicts.
Frequently Asked
What is a git worktree? A linked working directory attached to the same repository, with its own checked-out branch and index. It lets you have several branches checked out at once in different folders.
What is the difference between git worktree and git branch? A branch is a pointer to a commit. A worktree is a folder where a branch is checked out. You need a branch (or detached HEAD) per worktree, and worktrees let multiple branches be active at the same time.
What is the difference between git worktree and git clone? A clone copies the whole repository, history included. A worktree shares the existing repository's history, so it is cheaper, and branches and commits show up in every worktree immediately.
How do I list git worktrees? Run git worktree list. Add -v for lock reasons, or --porcelain for stable machine-readable output.
How do I delete a git worktree? Run git worktree remove <path>. It refuses if there are untracked or modified files unless you add --force. If you already deleted the folder, run git worktree prune.
Can I check out the same branch in two worktrees? Not by default. Git refuses, and --force overrides the check. Create a new branch for the second worktree instead.
Does Claude Code support git worktrees? Yes. Use claude --worktree <name> (or -w) to start a session in a new isolated worktree under .claude/worktrees/. Subagents can also run in their own worktrees with isolation: worktree.
How do I run multiple Claude Code sessions at once? Start each one with claude --worktree and a different name, in separate terminals. Each gets its own folder and branch.
Are node_modules shared between worktrees? No. A worktree is a fresh checkout, so install dependencies in each one.
Does a worktree include my .env file? No, because it is untracked. With Claude Code, list such files in a .worktreeinclude file and Claude copies them into worktrees it creates.