Git worktrees provide a clean, efficient way to work on multiple branches at once without juggling stashes, temporary commits, or extra clones. This article walks through a concrete workflow for adopting git worktree in everyday development.
Why git worktree?
In a typical Git workflow, switching branches while you have uncommitted work forces you to choose between stashing, WIP commits, or creating another clone of the repository. Git worktrees give you another option: multiple checked‑out branches from the same repository, each in its own directory, sharing a single .git data store.
This is especially useful when:
- You frequently interrupt a feature for hotfixes, reviews, or experiments.
- Your project has heavy dependencies (node modules, large virtualenvs, Gradle caches), making multiple clones expensive.
- You want to run tests or builds for several branches in parallel on the same machine.
One‑time setup and conventions
Start from an existing clone of your repository, with main (or develop) checked out:
git worktree list
Initially, you should see only the main worktree (the directory you’re in), showing its path, commit, and branch.
Choose a consistent convention for worktree locations, such as:
- A
.worktrees/directory inside the main repo (e.g..worktrees/feature-new-ui). - Or sibling directories (e.g.
../project-feature-new-ui).
The important part is that each worktree has a unique, meaningful path and that you avoid nesting one Git worktree inside another, which can confuse Git’s metadata.
Creating a worktree for an existing branch
Suppose your remote has a branch feature/new-ui that you want to work on without leaving main in your primary directory.
From the main repo directory:
git fetch origin
git worktree add .worktrees/new-ui feature/new-ui
cd .worktrees/new-ui
Key points:
git worktree add <path> <branch>creates a new directory at<path>and checks out<branch>there.- The new directory behaves like a normal working copy: you edit files, run tests, commit, and push as usual.
Your typical flow inside that worktree looks like:
# already in .worktrees/new-ui
git status
# edit files, run tests
git commit -am "Implement new UI"
git push -u origin feature/new-ui
When you’re done for now, you can simply cd back to the main directory, which still has your original branch and working state untouched.
Starting a new feature in its own worktree
Very often, the branch doesn’t exist yet; you want to create it and work in a dedicated directory from the start.
From the main repo directory:
git fetch origin
git worktree add -b feature/new-api .worktrees/new-api origin/main
cd .worktrees/new-api
Here:
-b feature/new-apitells Git to createfeature/new-apias a new branch.origin/mainis the base commit; you can usemain,develop, or any other starting point appropriate to your branching model.
Now you can develop the feature completely within .worktrees/new-api, while the main directory remains on main for reviews, builds, or other work.
Managing multiple active worktrees
Over time, you might accumulate several active worktrees: a couple of feature branches, a long‑running refactor, and maybe a release branch.
To see what’s active:
git worktree list
The output lists each worktree’s path, current commit, and checked‑out branch, with the main worktree first. For example:
/home/user/project a1b2c3d [main]
/home/user/project/.worktrees/new-ui d4e5f6 [feature/new-ui]
/home/user/project/.worktrees/new-api 987654 [feature/new-api]
With this view you can:
- Jump between directories instead of switching branches in a single directory.
- Keep long‑running work (like big refactors) open and test them periodically without disturbing your day‑to‑day branch.
- Run multiple test suites or build processes in parallel on different branches.
Each worktree is a self‑contained environment for that branch; there is no “one worktree, many branches” mode—every worktree corresponds to a single branch or detached HEAD at a time.
Handling urgent hotfixes and reviews
A classic use case: you’re mid‑feature when a production incident appears.
Instead of stashing or committing half‑baked work:
-
Leave your feature worktree as is.
-
From the main repo directory, create a hotfix worktree:
git fetch origin git worktree add .worktrees/hotfix-critical hotfix/critical-bug cd .worktrees/hotfix-critical -
Apply the fix, commit, and push:
# implement fix git commit -am "Fix critical bug in production" git push origin hotfix/critical-bug -
Once the hotfix is merged back into
mainand any release branches, you can remove this worktree (see next section).
You can use the same pattern for:
- Checking out a PR branch to test it locally.
- Pairing on a branch without touching your current environment.
- Running experiments on a throwaway branch in a dedicated directory.
Cleaning up: remove and prune
Worktrees are cheap, but they will accumulate if you never remove them.
Once a branch is merged and you no longer need its dedicated directory:
# from the main repo directory (or any worktree in the same repo)
git worktree remove .worktrees/new-ui
Important details:
git worktree remove <path>removes the worktree directory and its administrative entry; it does not necessarily delete the Git branch itself.- The worktree must be clean (no untracked or modified tracked files) unless you add
--force, which will discard uncommitted changes.
Over time you may manually delete directories or encounter stale entries (e.g. after a crash). To clean up those leftovers:
git worktree prune --verbose
This command prunes worktree records whose directories no longer exist, using expiration rules that can be configured via Git settings like gc.worktreePruneExpire. You can also use --expire <time> with prune if you want to only remove older, unused entries.
A light maintenance habit is:
- Remove the worktree for a feature once its PR is merged and the branch is closed.
- Run
git worktree pruneoccasionally to clean up stale metadata.
Practical guidelines and best practices
To make git worktree a reliable part of your team’s workflow, adopt a few simple rules:
- Organize worktrees predictably: Use stable directory patterns (
.worktrees/<branch-name>or similar) and use names that reflect the branch, like.worktrees/feature-auth-api. - Avoid nesting: Never create a worktree inside another worktree’s directory; this can confuse Git’s detection of repositories and worktrees.
- Keep your base branches fresh: Regularly fetch and update
main/developand rebase or merge them into your feature worktrees to minimize integration surprises. - Clean up after merges: Remove worktrees you no longer need, then prune occasionally to ensure
git worktree listremains readable and accurate. - Check Git version: Some newer options and behaviors (like more detailed
listoutput and improved prune behavior) depend on having a reasonably up‑to‑date Git installation.
By following this workflow—create a worktree per active branch, keep them organized, and clean them up when done—you get parallel branch development with far less friction than stashes, temporary commits, or multiple clones, while still relying on standard Git primitives.
Recent Comments