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-api tells Git to create feature/new-api as a new branch.
  • origin/main is the base commit; you can use main, 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:

  1. Leave your feature worktree as is.

  2. 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
  3. Apply the fix, commit, and push:

    # implement fix
    git commit -am "Fix critical bug in production"
    git push origin hotfix/critical-bug
  4. Once the hotfix is merged back into main and 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 prune occasionally 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/develop and 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 list remains readable and accurate.
  • Check Git version: Some newer options and behaviors (like more detailed list output 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.