Skip to content
masterclass Buddy

Git · Command

git worktree

git worktree lets one repository have several working directories, so you can check out more than one branch at once. Its subcommands add, list, lock, unlock, move, remove, prune and repair these linked worktrees.

Last updated

How it works

A repository has one main worktree (none if it is bare) and can have any number of linked worktrees. Running add creates a directory for the new worktree plus a private admin folder under $GIT_DIR/worktrees/<id>. The new directory gets a small .git file that points back to that folder. All worktrees share the same objects, refs and config. Each one keeps its own HEAD, index and pseudo-refs. If you omit <commit-ish>, add uses the last part of the path as the branch name and creates that branch from HEAD if it doesn't exist yet.

Syntax

git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]] [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
git worktree list [-v | --porcelain [-z]]
git worktree lock [--reason <string>] <worktree>
git worktree move <worktree> <new-path>
git worktree prune [-n] [-v] [--expire <expire>]
git worktree remove [-f] <worktree>
git worktree repair [<path>...]
git worktree unlock <worktree>

Parameters

NameTypeDescription
<path>pathDirectory where add creates the new worktree. If no branch is given, its last component becomes the branch name.
<commit-ish>commit-ishWhat to check out in the new worktree. A bare '-' means @{-1} (the previous branch).
<worktree>pathNames an existing worktree by relative or absolute path, or by its last path components if they are unique.
-b / -B <new-branch>branch nameCreates a new branch at <commit-ish> (HEAD by default) for the worktree. -B resets the branch if it already exists.
-f / --forceflagOverrides safety checks: a branch checked out elsewhere, a missing path, or an unclean worktree. Give it twice for locked worktrees.
-d / --detachflagWith add, gives the new worktree a detached HEAD instead of a branch.
--orphanflagWith add, starts the worktree with an empty tree and index on a new unborn branch.
--lock / --reason <string>flag / stringLocks the worktree as soon as it is created, optionally recording why.
--porcelain / -zflagWith list, prints machine-readable output; -z ends each line with NUL instead of a newline.
-n / --dry-run, --expire <time>flag / timeWith prune, reports what would be removed without removing it, or only prunes missing worktrees older than <time>.

Key points

  • Refs are mostly shared between worktrees. Pseudo-refs such as HEAD belong to each worktree, and so do refs under refs/bisect, refs/worktree and refs/rewritten.
  • Every linked worktree gets its own admin folder under $GIT_DIR/worktrees. The folder is usually named after the worktree's directory, with a number added if that name is taken.
  • Locking a worktree keeps prune from deleting its admin data. That matters when the worktree sits on removable media or a network share. A lock also blocks move and remove.
  • Passing --lock to add locks the worktree as part of creating it. That is safer than running lock afterwards.
  • Scripts should use list --porcelain, preferably with -z, because that format won't change between versions or with user settings.
  • add --no-checkout creates the worktree without checking files out. That gives you a chance to set things up first, for example sparse-checkout.
  • To name a worktree in a command, the tail of its path is enough as long as no other worktree's path ends the same way.

Common mistakes

  • A branch can be checked out in only one worktree at a time. add refuses to check out a branch that another worktree is using unless you pass --force.
  • remove fails if the worktree has untracked or modified files. You need --force for that, and --force twice if the worktree is locked.
  • move can't relocate the main worktree or a linked worktree that contains submodules. If you move them by hand, run repair afterwards to fix the links.
  • Using multiple worktrees with submodules is still experimental. The docs advise against checking out a superproject more than once.

Example: Hotfix in a temporary worktree without touching your current work

#!/usr/bin/env bash
set -euo pipefail

# Create ../hotfix on a new branch based on main
git worktree add -b hotfix ../hotfix main

# Do the fix there; your current checkout stays as it is
(
  cd ../hotfix
  echo "fix" >> CHANGELOG.md
  git commit -am "Hotfix: patch release"
)

# See every worktree in script-friendly form
git worktree list --porcelain

# Clean up when done (fails if ../hotfix has uncommitted changes)
git worktree remove ../hotfix

# Clear admin data for any worktree folders that were deleted by hand
git worktree prune --verbose

The script commits a hotfix on its own branch in a separate directory, lists all worktrees, then removes the temporary one and prunes leftover entries, all without disturbing the original checkout.

When to use it

Urgent fix in the middle of a refactor

Your working tree is full of moved and new files that you don't want to stash. You add a temporary worktree on main, commit the fix there, and remove the worktree when you're done.

Throwaway test checkout

Run git worktree add -d to get a detached worktree for trying out a build or experiment. No branch is created and your current branch is left alone.

Reviewing several branches side by side

Keep long-lived worktrees for a release branch and a feature branch, so you can build and test both at once without switching back and forth.

Worktree on removable storage

Keep a worktree on an external drive and lock it with a reason, so automatic pruning doesn't delete its admin data while the drive is unplugged.

Interview questions

QWhat do linked worktrees share with the main worktree, and what does each one keep separately?

Every worktree uses the same object database, the same refs under refs/, and by default the same config file. Each worktree has its own HEAD, index and other pseudo-refs, plus refs under refs/bisect, refs/worktree and refs/rewritten. These per-worktree files live in $GIT_DIR/worktrees/<id>, and $GIT_COMMON_DIR points back to the main .git directory.

Follow-up: How do you read another worktree's HEAD from the one you're in? Use the special ref paths: main-worktree/HEAD for the main worktree, or worktrees/<name>/HEAD for a linked one. Commands like git rev-parse resolve these correctly.

QYou deleted a linked worktree's folder with rm -rf. What happens, and how do you clean up?

The admin entry under $GIT_DIR/worktrees stays behind, and git worktree list marks it as prunable. Git eventually removes it on its own, depending on gc.worktreePruneExpire. You can also run git worktree prune from any worktree right away, adding -n first to preview what would go.

Follow-up: What if you moved the folder instead of deleting it? Run git worktree repair from inside the moved worktree, or from any worktree with the new path as an argument, and Git rewrites the gitdir links instead of pruning the entry.

QHow do you give one worktree settings that the others don't get?

Turn on the extension with git config extensions.worktreeConfig true. Then git config --worktree writes to that worktree's own config.worktree file. If core.worktree or core.bare is set in the shared config, move it into the main worktree's config.worktree. Older Git versions can't open repositories that have this extension enabled.

Follow-up: Why can turning on worktreeConfig break a bare repository setup? Once the extension is on, core.bare=true in the shared config no longer applies only to the main worktree, so it affects every worktree; you have to move it into the main worktree's config.worktree.

  • git-checkout
  • git-switch
  • git-branch
  • git-stash
  • git-config
  • git-rev-parse
  • git-update-ref
  • gitrepository-layout

Source: Git - git-worktree Documentation. Checked 2026-11-02.