Git worktrees let you keep separate checkouts of one repository open at the same time. Use a distinct branch and directory for each development task, select the starting commit explicitly, and inspect each worktree’s changes before removing it. Your original checkout can keep its unfinished edits while another task starts from a committed revision.
The separation is at the checkout level. Worktrees still share repository objects and most configuration; they do not isolate databases, ports, credentials, or remote effects. Parallel development needs those boundaries too.
Know what is separate before creating anything
A branch names a line of commits. A worktree supplies a working directory and index in which to edit and stage files. Two tasks can therefore use the same repository history while keeping their working files apart. Git’s worktree manual documents this arrangement and normally prevents the same branch from being checked out in two worktrees at once.
Start by inspecting what you already have:
git status --short
git branch --show-current
git worktree list
Record which checkout owns unfinished changes. Decide whether the new task should start at your current HEAD, a named integration branch, or another specific commit. Those choices are different when your current branch has extra commits or the remote tracking branch is stale.
In a real repository, fetch if current remote state is required and access is authorized. Then inspect the intended base. Creating a worktree does not itself prove that its base includes the latest upstream changes.
Create a new task from a known commit
From the original repository, this example creates a new branch and a sibling directory:
git worktree add -b feature/header ../orders-header HEAD
HEAD makes the starting point explicit. The new branch begins at the current commit. Uncommitted changes in the original directory are not part of that commit and do not appear in the new checkout.
Open a terminal or editor in ../orders-header, then confirm its identity:
git -C ../orders-header branch --show-current
git -C ../orders-header status --short
Use a directory name that remains understandable in an editor window, terminal tab, and process list. A clear name helps prevent running the right command in the wrong checkout.
For an existing branch, omit -b:
git worktree add ../orders-review feature/existing-change
If Git says the branch is already checked out, inspect git worktree list and use that checkout when appropriate. Forcing a second checkout of the same branch removes a useful safeguard and usually makes task ownership harder to reason about.
Prepare the runtime separately
A worktree contains checked-out files. It is not automatically a complete development environment. Follow the repository’s setup procedure for dependencies, generated files, and configuration. Avoid copying credentials from another checkout as a convenience.
Two directories can still point at the same database or use the same development server port. Give concurrent tasks separate test databases or schemas where required, distinct ports, and suitable output directories. A shared package cache may be intentional; a shared mutable build directory may not be.
Before asking two agents to work simultaneously, assign file or feature ownership and identify shared interfaces. Worktrees prevent one agent from directly overwriting another’s uncommitted file in a different checkout. They do not prevent both agents from designing incompatible changes to the same API.
Review both the working changes and the branch change
While developing, inspect unstaged and staged work in the task directory:
git -C ../orders-header diff
git -C ../orders-header diff --cached
Run the relevant checks there. Evidence from the original checkout does not validate different files in the worktree.
Once changes are committed through your normal workflow, compare the branch with its intended base:
git diff main...feature/header --
The three-dot comparison uses the branches’ merge base, as described in Git’s diff documentation. It is useful for inspecting the committed change relative to shared history. It does not include uncommitted files, so it does not replace the earlier status and diff checks.
Integration still requires review. Merge or cherry-pick according to the repository’s process, resolve any conflicts, and run checks on the integrated result. Two branches passing independently does not prove that their combination passes.
Remove the checkout only after accounting for its contents
Before cleanup, inspect tracked changes, untracked files, and ignored files that may contain useful local artifacts:
git -C ../orders-header status --short
git -C ../orders-header status --short --ignored
An ignored report, fixture, or local configuration may matter even though it is absent from the normal status output. Copy needed artifacts to an approved location before removing their directory. Check the branch’s commit history and integration status separately.
Then remove a clean linked checkout using Git:
git worktree remove ../orders-header
In the local exercise, Git refused to remove a worktree with modified tracked files. Treat that refusal as a request to inspect and preserve the work. Do not add --force just to complete cleanup.
Removing a linked worktree does not delete its branch. This is useful when a reviewed commit should remain available after the directory is no longer needed. Branch deletion is a separate decision. Git’s branch documentation describes deletion and merged-branch checks; inspect the intended integration target before relying on them.
If a directory has already been moved or deleted manually, inspect the worktree list and Git’s repair or prune commands. Pruning cleans stale administrative records; it is not a backup mechanism. A worktree on an intermittently available disk can be locked to protect its registration while the disk is absent.
What the disposable exercise verified
The guide’s core lifecycle was run in a temporary repository with Git 2.54.0 on macOS. The original checkout had an unfinished edit to app.txt. A new feature/header worktree started from committed HEAD.
| Operation | Observed result |
|---|---|
Read app.txt in the new checkout |
It contained the committed baseline. |
| Read it in the original checkout | The unfinished edit remained. |
Check out feature/header in another worktree |
Git refused, exit 128. |
| Remove the modified feature worktree | Git refused, exit 128. |
| Commit the synthetic feature change and review the branch diff | The diff showed the intended one-line change. |
| Remove the now-clean feature worktree | Removal succeeded. |
Read feature/header:app.txt afterward |
The committed feature content still existed. |
The temporary fixture and its synthetic commits were discarded after the exercise. No application repository was merged, pushed, or cleaned. The test establishes these local Git behaviors; it does not establish that parallel tasks finish faster or that a particular development environment is isolated.
Use worktrees when keeping tasks in separate directories makes their state easier to inspect. Give each task a known base, a clear owner, and its own verification evidence, then clean up only after its files and commits are accounted for.
Documentation checked October 28, 2026. The current online worktree manual identified Git 2.56.0; the commands above were exercised on Git 2.54.0.