Git Worktrees for Parallel CI Builds & Hotfix Isolation¶
git worktree lets you check out multiple branches simultaneously in
separate working directories, all sharing one .git database. A DevOps
engineer juggling a release build, an emergency CVE hotfix, and a CI
debug session no longer has to git stash dance between them.
Why a DevOps Engineer Needs This¶
- Run a long production build on
release/2.4while you keep editing onmain. - Reproduce a customer's reported bug by checking out their exact SHA in a sidecar worktree — without stashing, without cloning again.
- Run parallel CI matrix jobs locally: one worktree per
GOOS/ARCHcombination, each with its owndist/artifact. - Compare two branches side-by-side in your editor (or a diff tool) without constantly switching HEAD.
- Hotfix flow:
mainkeeps moving forward,hotfix/CVE-2024-9999lives in a dedicated worktree, you cut the patch tag, merge, and remove it.
Core Concepts¶
| Term | Meaning |
|---|---|
| Main worktree | Your normal repo dir; always on whatever branch you checked out |
| Linked worktree | Additional checkout under <repo>/../<branch>-wt (or anywhere) |
Shared .git |
All worktrees share the same object database and reflog |
| One branch | A branch (or detached SHA) can only be checked out in one worktree at a time |
Quick Start¶
# Add a worktree for a hotfix branch (creates branch if missing)
git worktree add ../hotfix-cve-2024-9999 -b hotfix/CVE-2024-9999 main
# Add a worktree pinned to a specific SHA (reproducible CI)
git worktree add ../ci-debug-9f3a1bc 9f3a1bc
# Add a worktree for an existing remote branch
git worktree add ../feature-flag feature/flag-rollout
# List all worktrees
git worktree list
# Remove a worktree when done
git worktree remove ../hotfix-cve-2024-9999
# If the branch is fully merged you can prune it too:
git branch -d hotfix/CVE-2024-9999
git worktree prune
Pattern 1: Parallel Matrix Build (Local CI)¶
When you need to verify a release across architectures without firing up full CI:
# 1. Bootstrap one worktree per target
for GOARCH in amd64 arm64; do
git worktree add ../build-${GOARCH} release/2.4
done
# 2. In each, build & drop artifact in a known location
( cd ../build-amd64 && GOARCH=amd64 go build -o dist/app-amd64 ./cmd/app )
( cd ../build-arm64 && GOARCH=arm64 go build -o dist/app-arm64 ./cmd/app )
# 3. Clean up
git worktree remove ../build-amd64
git worktree remove ../build-arm64
Pattern 2: Hotfix Isolation¶
# main is dirty with WIP; you need a CVE patch *now*
git stash push -u -m "wip: half-finished refactor"
git worktree add ../hotfix ../main -b hotfix/CVE-2024-9999
cd ../hotfix
# ... edit, commit, tag, push ...
git tag -s v2.4.1 -m "CVE-2024-9999 patch"
git push origin hotfix/CVE-2024-9999 --follow-tags
# Back to main
cd -
git worktree remove ../hotfix
git stash pop
Pattern 3: Reproducing a Customer's Bug¶
A support ticket says: "Crashes on commit a1b2c3d with input X."
You don't want to lose your in-progress feature work:
git worktree add ../repro-a1b2c3d a1b2c3d
cd ../repro-a1b2c3d
./run-with-customer-input.sh
# ... gdb, strace, bisect ...
cd -
# worktree stays put until you're finished investigating
Pattern 4: Detached Worktree for Bisecting CI¶
Combine with git bisect to find which commit broke a CI pipeline,
without losing your current branch context:
git worktree add ../bisect-runner HEAD
cd ../bisect-runner
git bisect start
git bisect bad HEAD
git bisect good v2.3.0
# bisect will checkout candidates inside this worktree — your main
# checkout is untouched and keeps your editor state intact
Pitfalls¶
- Same branch, two worktrees — disallowed. Git refuses; pick a different branch or a detached SHA.
- Submodules in worktrees need
git submodule update --initin each new worktree; they're not auto-shared. git gcandgit pruneare global — they affect every worktree's reachable objects. Rungit worktree pruneafterwards to clean up stale worktree metadata.- Editor / IDE must be opened per-worktree; opening the same project in two JetBrains windows can confuse indexing.
- Sparse-checkout is per-worktree; configure separately if you want different file sets per checkout.
Useful Aliases¶
# ~/.gitconfig
[alias]
wt = worktree
wta = worktree add
wtl = worktree list
wtr = worktree remove
wtp = worktree prune
Verification¶
git worktree list
# /home/devops/myapp abc1234 [main]
# /home/devops/build-amd64 def5678 [release/2.4]
# /home/devops/hotfix 9f3a1bc [hotfix/CVE-2024-9999]
ls -la ../build-amd64/.git # points back to the main repo's .git/worktrees/
When Not to Use Worktrees¶
- You only need to peek at one file from another branch → just use
git show branch:pathorgit restore --source=branch -- path. - The other branch is on a different filesystem (e.g. NFS) with weird lock semantics — clone separately instead.
- You're orchestrating dozens of builds in CI — a build matrix in your CI tool is the right answer; worktrees are for local parallelism.