Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXXIII · WorktreesWorktrees

Creating and removing worktrees — git worktree add, -b, --detach, --force

Advanced⏱ ~21 mingit

What you'll learn

  • Create a worktree pointing at an existing branch, a new branch, or a detached commit
  • Use --force to recover from a "branch already checked out" conflict in a controlled way
  • Remove a worktree cleanly or forcefully and understand the difference
  • Map each flag (-b, --detach, --force) to the production scenario that justifies it

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

The first lesson established that a worktree is a second working tree attached to the same .git directory. This lesson covers the mechanics: how to create one with the right initial state, and how to remove one when it has done its job. The create command has three flags that change behaviour (-b, —detach, —force); the remove command has one flag that overrides safety. Each flag maps to a specific production scenario.

The default create: add with an existing branch

The simplest create is git worktree add $PATH $BRANCH. It creates a new working tree at $PATH, checks out $BRANCH in it, and records the link under .git/worktrees/$BRANCH_BASENAME:

git worktree add ~/work/iac-hotfix hotfix/vpn-cert
# Preparing worktree (new branch 'hotfix/vpn-cert')
# HEAD is now at 7g8h9i0

The branch must already exist. If it does not, git worktree add fails with fatal: invalid reference: hotfix/vpn-cert. The working tree path must not be an existing non-empty directory. If it is, the add fails with fatal: '$PATH' already exists. The target branch must not be checked out in another worktree. If it is, the add fails with fatal: 'hotfix/vpn-cert' is already checked out at '$OTHER_PATH'.

These three failure modes are intentional. Each one is a guard against a state the user almost certainly did not want: a branch that does not exist, a working tree path that would clobber an existing directory, or a branch that would be checked out twice.

Adding with a new branch: -b

The -b flag creates the branch at the same time as the worktree, pointing at an optional start-point:

# New branch 'feature/iam-rotation' from origin/main, in a new worktree
git worktree add -b feature/iam-rotation ~/work/iac-feature-iam origin/main

# New branch 'hotfix/s3-bucket' from a specific commit (the rollback commit)
git worktree add -b hotfix/s3-bucket ~/work/iac-rollback a1b2c3d

The -b form is the worktree equivalent of git checkout -b. The start-point defaults to HEAD if omitted; explicitly naming it (origin/main, a tag, a commit) is the production discipline because it makes the branch’s parent unambiguous. A common incident is a worktree created against a local main that was three days behind origin/main; the new branch points at the wrong base and the PR diff includes unrelated changes.

Detached HEAD: —detach

The --detach flag creates the worktree in detached HEAD state — no branch is checked out, only a commit. This is the worktree equivalent of git checkout --detach:

# Detached HEAD at a specific commit (an old release tag's commit)
git worktree add --detach ~/work/iac-release-1.4 v1.4.0

# Detached HEAD at HEAD (a quick scratch worktree for inspection)
git worktree add --detach ~/work/iac-scratch

Detached-HEAD worktrees are useful for inspecting old states without creating a branch, for bisect sessions that need to jump between commits without leaving named refs behind, and for short-lived read-only checkouts of a release tag. The worktree keeps the commit reachable from its own HEAD; commits made on top of the detached HEAD are reachable only from that worktree’s reflog, and disappear when the worktree is removed without preserving them.

Forcing through a conflict: —force

The --force flag overrides two of the guards above: a non-empty target directory and a branch already checked out elsewhere. Each case is a different operational decision:

# Force-create into a non-empty directory that is known to be stale
git worktree add --force ~/work/iac-feature-iam feature/iam-rotation

# Force-create against a branch already checked out in another worktree
# (the OTHER worktree's index/HEAD will be left in an indeterminate state)
git worktree add --force ~/work/iac-feature-iam-copy feature/iam-rotation

The --force flag is appropriate in two cases: the target directory is a stale leftover that the user has verified is safe to overwrite, and the user is recovering from a corrupted worktree metadata state that the normal add refuses. Neither case is routine; both should be documented in the runbook when they happen.

Removing a worktree: clean and forceful

The remove command has two forms:

# Clean remove — fails if the worktree has local changes or untracked files
git worktree remove ~/work/iac-hotfix

# Forceful remove — drops the worktree even if it has local changes
git worktree remove --force ~/work/iac-scratch

The clean form is the production default. It refuses to drop a worktree that has uncommitted changes, untracked files that match .gitignore-negation rules, or locks from a previous git worktree lock (covered in lesson 06). The forceful form drops the worktree regardless of state; any uncommitted changes in it are lost.

# Inspect before removing
git worktree list
# /home/alice/work/iac                       a1b2c3d [main]
# /home/alice/work/iac-feature-iam           d4e5f6a [feature/iam-rotation]
# /home/alice/work/iac-scratch               7g8h9i0 (detached HEAD)

# Clean remove of the scratch worktree
git worktree remove ~/work/iac-scratch
git worktree list
# /home/alice/work/iac                       a1b2c3d [main]
# /home/alice/work/iac-feature-iam           d4e5f6a [feature/iam-rotation]

After git worktree remove, the directory is gone and the .git/worktrees/$NAME metadata record is removed. The branch itself is not deleted — git worktree remove does not touch refs. Deleting the branch is a separate git branch -d (or -D if the branch has not been merged).

Production discipline

  1. Default to the clean form. git worktree add without --force and git worktree remove without --force. The flags exist for the rare cases where the guards they bypass are wrong, not for routine use.
  2. Name worktree paths off the parent directory. When the main worktree is at ~/work/iac, name linked worktrees ~/work/iac-feature-iam, ~/work/iac-hotfix, etc. The sibling naming makes git worktree list easy to read and prevents accidental nesting.
  3. Specify the start-point explicitly with -b. Defaulting to HEAD is a common source of “wrong-base” PRs.
  4. Never --force a worktree onto an already-checked-out branch. The other worktree’s state is corrupted. If a branch needs to be in two places, use a clone.
  5. Remove worktrees when the branch is merged. A worktree left checked out on a merged branch is a future “branch already checked out” error waiting to happen.

Cross-course references

  • Git, CI/CD & GitOps - Part V (HEAD) lesson 03 covers the detached-HEAD state that --detach produces; this lesson applies it to the worktree primitive.
  • Git, CI/CD & GitOps - Part IX (Merging) lesson 05 covers aborting a merge, which is the same idea as --force for recovery from a wedged state.
  • CI/CD Pipeline Patterns - Part III (CheckoutStrategies) uses git worktree add in CI runners; the --force flag is rarely needed there but --detach is routine.

Quiz

Knowledge check · 4 questions

  1. Q1. An engineer runs `git worktree add ~/work/iac-fix hotfix/vpn-cert` and gets the error `fatal: 'hotfix/vpn-cert' is already checked out at '/home/alice/work/iac-vpn'`. What is the safest next step?

  2. Q2. `git worktree remove` deletes the branch the worktree was checked out on, in addition to removing the working tree directory and the .git/worktrees/$NAME metadata.

  3. Q3. List the three flags that change the create semantics of `git worktree add`, and describe one production scenario that justifies each.

  4. Q4. Pick the right `git worktree add` invocation for each of three production situations, and justify the choice.

    An infrastructure team needs three worktrees off the same Terraform repository: (a) a new feature branch `feature/iam-rotation` based on `origin/main` for an in-progress refactor; (b) a read-only inspection of release `v1.4.0` to investigate a bug report; (c) a hotfix branch `hotfix/s3-bucket` based on the rollback commit `a1b2c3d` for an emergency fix.

Passing score: 75%. Answers are checked in this browser.