Git has long allowed several working copies to hang off a single repository, each on its own branch and in its own directory. The git worktree command avoids stacking stash entries to jump between tasks, and re-cloning a whole project just to open a quick fix. The mechanism is stable, present in any recent Git, and pays off well beyond very large repositories.
The problem worktrees solve
The scenario is common: a feature is in progress, the working tree is dirty, and an urgent fix lands on the production branch. The usual reflexes each carry a cost. git stash sets work aside but forces you to juggle an invisible stack, and it separates neither installed dependencies nor build artefacts. A full re-clone duplicates the entire history and burns disk for a repository already present locally.
A worktree offers a third path: an extra directory, attached to the existing repository, holding another branch. Work in progress stays intact in its directory, the fix opens alongside it, and the two coexist without stepping on each other.
One branch per directory, a single history: the context switch no longer costs a stash.
Create, list, locate a worktree
A worktree is created in one command, from an existing branch or by creating it on the way. The first argument is the path of the new directory, the second the branch to place in it.
# Add a worktree for an existing branch
git worktree add ../paiement-hotfix hotfix/paiement
# Create the branch together with the worktree
git worktree add -b correctif-tva ../correctif-tva main
# List the worktrees attached to the repository
git worktree listThe main directory stays the default worktree; the others are added to it. git worktree list shows their path, current commit and associated branch, giving an immediate overview of the open fronts.
What is shared, what is not
All worktrees of a repository share a single .git directory: history, objects, branches and remotes are common. A commit made in one worktree is immediately visible from the others, without push or fetch. That sharing is exactly what keeps the operation cheap on disk compared to a clone.
Each worktree, however, has its own working files, index and HEAD. Whatever lives outside Git’s tracking does not follow: installed dependencies (such as node_modules), ignored environment files and build artefacts are specific to each directory. That is an advantage, since a build run in one worktree does not overwrite another’s, but it means reinstalling dependencies in each new directory.
| Criterion | git stash | New clone | git worktree |
|---|---|---|---|
| Simultaneous working copies | No | Yes | Yes |
| Shared history and objects | Yes | No (duplicated) | Yes |
| Disk cost | None | High | Low (working files only) |
| Isolated dependencies and build | No | Yes | Yes |
| Context switch | Push / pop | Change folder | Change folder |
Concrete use cases
The urgent fix is the textbook example, but the tool serves several other daily routines:
- Code review: checking out a pull request’s branch in a dedicated worktree lets you actually run it, test it and compare it, without disturbing work in progress.
- Long builds: an expensive compilation or test suite can run in one worktree while development continues in another.
- Bisect: isolating a regression with
git bisectin a separate worktree keeps the main working tree clean. - Comparing versions: keeping two branches open side by side to weigh two implementations of the same page or API.
For a freelancer juggling several engagements, the benefit is clear: a client repository can hold the billed feature branch and the urgently requested production fix in parallel, without mixing and without re-cloning.
Handy details for daily use
A few points help you get the most from the mechanism. In a secondary worktree, the .git is not a directory but a plain file pointing to the main repository: that link is what grants access to the shared history. Since configuration and hooks live in the common repository, they apply to every worktree, keeping environments uniform without any manual copying.
Three commands round out the toolkit. git worktree add --detach creates a directory in a detached state, handy for a throwaway test without creating a branch. git worktree move relocates an existing worktree to another path. git worktree lock protects one that lives on removable media or a network mount, so prune does not remove it while it is away. On the editor side the logic is immediate: each worktree opens as an independent project folder, with its own window and its own terminal.
That leaves the question of placement. Putting worktrees in a sibling directory of the project, or in a dedicated folder gathering the copies of one repository, keeps the tree readable and avoids nesting one worktree inside another. Because remotes are shared, a git fetch run from any worktree updates references for all of them, sparing repeated network round trips. That saving, invisible on a small project, becomes tangible on a heavy repository where each extra clone would cost minutes and gigabytes.
Clean up and dodge the traps
Once the branch is merged, the worktree is removed cleanly. Deleting the directory by hand leaves orphan references that git worktree prune clears.
# Remove a worktree once the branch is merged
git worktree remove ../paiement-hotfix
# Clean up references to manually deleted worktrees
git worktree pruneThree traps to know. The same branch cannot be checked out in two worktrees at once: Git refuses it to avoid two diverging histories on the same reference. Dependencies and ignored files are not shared, so reinstall them in each directory. Finally, relative paths and scripts that assume a fixed project root can surprise you if the worktree lives elsewhere in the tree.
What to take away
Worktrees beat the stash-plus-re-clone pair whenever you need two contexts open at once. They share history to stay light, isolate working files to avoid collisions, and are handled with three commands: add, list, remove. The habit to build is cleaning up finished directories, so you do not leave forgotten working copies lying around.
On my freelance engagements, worktrees settled the most annoying case: a production fix that lands in the middle of a half-written feature. No more stash to rediscover three days later, no more node_modules recompiled the wrong way round. One directory per context, and the mind stays clear. The only reflex to install is remove: without it, you pile up phantom worktrees you eventually no longer dare to touch — Simon Janvier
Further reading
Git — Official git-worktree documentation
