The One-Command Safety Net: Using Git Worktrees to Experiment Fearlessly on Big Codebases
Learn how Git worktrees let you experiment safely on large codebases without extra clones, constant branch switching, or risky stashes—and how to integrate them into your daily workflow.
The One-Command Safety Net: Using Git Worktrees to Experiment Fearlessly on Big Codebases
When you’re working on a large codebase, switching tasks can feel risky and expensive. You might be halfway through a big refactor when a production bug pops up. Do you stash? Commit half-broken code? Clone the repo again and wait for yet another massive dependency install?
None of those options is great.
Git worktrees give you a much better way: multiple independent working directories, all backed by a single repository. With one extra command, you get a safe sandbox to experiment, fix bugs, or review code—without touching your main workspace.
This post walks through what worktrees are, why they’re ideal for big codebases, and how to use them day-to-day.
What Is a Git Worktree?
A Git worktree is an additional working directory attached to the same .git repository. Each worktree is usually checked out to a different branch, but all share the same underlying object database.
In practice, that means:
- You can have multiple branches checked out simultaneously, each in its own directory.
- All worktrees share the same
.githistory and objects, so you’re not duplicating the repo. - Each worktree has its own isolated filesystem state: its own modified files, build artifacts, and local config.
This is fundamentally different from just cloning the repo again:
- Multiple clones = multiple
.gitdirectories, duplicated history, repeatedgit fetch/git pull, and often duplicated dependencies. - Multiple worktrees = one
.gitdirectory and object database, cheap extra directories, and shared history.
Why Worktrees Shine on Large Codebases
On small projects, constantly switching branches is annoying. On big projects, it becomes a workflow killer.
1. No More Constant Branch Switching
With worktrees, instead of:
git checkout feature-x # work # oh no, bug git stash git checkout hotfix-branch # fix bug git checkout feature-x git stash pop
You can do:
# main workspace: feature-x # create a separate worktree for the hotfix $ git worktree add ../project-hotfix hotfix-branch $ cd ../project-hotfix # fix bug here, independently
Both branches stay checked out, side by side. No stash juggling, no context loss.
2. No More Risky Stashes
Stashes often become a junk drawer of half-remembered changes. Worktrees let you keep each line of work in a real directory instead of a hidden stash stack.
- Each experiment lives in its own worktree directory.
- Your “main” directory (often on
mainordevelop) stays clean and reliable. - You don’t have to remember what’s in which stash or fear
git stash drop.
3. Avoid the Cost of Multiple Clones
For large repos, cloning multiple times hurts:
- Extra network usage and time to clone.
- Disk space wasted on duplicate
.gitdirectories. - Dependency installs (e.g.,
node_modules, build artifacts) repeated for each clone.
Worktrees solve this elegantly:
- One repo, one
.gitstorage. - Additional worktrees mostly add filesystem content, not another copy of Git history.
- Fetch once, use the same commits in multiple worktrees.
4. Safer Experimentation
Want to spike a risky refactor, try a new toolchain, or prototype an idea?
- Create a new worktree.
- Keep your primary workspace stable and production-ready.
- If the experiment goes nowhere, you can delete the entire directory in one go.
On big codebases where rebuilds, migrations, and tooling changes are expensive, this “sandbox per idea” model is incredibly valuable.
Getting Started: Basic Worktree Commands
All of the magic revolves around git worktree.
1. Listing Existing Worktrees
git worktree list
You’ll see something like:
/path/to/project abc1234 [main] /path/to/project-feature def5678 [feature/cool-idea] /path/to/project-bugfix 9ab0123 [bugfix/login]
Each line is a worktree: its path, current commit, and branch.
2. Creating a New Worktree
The general pattern:
git worktree add <path> <branch-or-commit>
Common use cases:
-
Start a new feature branch from main:
$ cd /path/to/project $ git fetch origin $ git worktree add ../project-new-feature origin/main $ cd ../project-new-feature $ git switch -c feature/new-api -
Check out an existing branch in a new directory:
$ git worktree add ../project-bugfix bugfix/1234 -
Work on a specific commit or tag:
$ git worktree add ../project-old-release v1.2.0
Now you have a new directory with its own git status, git log, and local changes—completely separate from other worktrees.
3. Removing a Worktree
Once you’re done with a worktree:
# from anywhere inside the repo $ git worktree list # find the path you want to remove $ git worktree remove /full/path/to/worktree
This is safer than just rm -rf because:
- Git cleans up its internal references to that worktree.
- You avoid leaving behind stale worktree entries that confuse
git worktree list.
Tip: Always commit or back up anything you care about before removing a worktree. Removing the worktree removes its working directory.
A Practical Daily Workflow with Worktrees
Here’s how you might structure your day using worktrees on a large codebase.
1. Keep a Stable “Home Base” Worktree
Use your original clone as your home base, typically on main or develop:
/path/to/project # always on main or develop
- You pull latest changes here.
- You run quick inspections, read code, and do non-destructive tasks.
- You don’t start risky work directly in this directory.
2. Create One Worktree Per Significant Task
For each substantial piece of work, create a dedicated worktree:
# feature work /path/to/project-feature-x /path/to/project-feature-y # hotfix /path/to/project-hotfix-123
Benefits:
- Each directory holds its own builds, logs, and editor configuration.
- You can open multiple IDE windows side by side, each bound to a different branch.
Example:
$ cd /path/to/project $ git fetch origin $ git worktree add ../project-feature-x origin/main $ cd ../project-feature-x $ git switch -c feature/x
3. Handling Interruptions and Context Switching
When a high-priority issue appears:
-
Do not touch your in-progress feature directory.
-
From your home base worktree, create a new directory for the fix:
$ cd /path/to/project $ git fetch origin $ git worktree add ../project-critical-fix origin/main $ cd ../project-critical-fix $ git switch -c hotfix/critical-issue -
Fix, test, push, and open a PR from that worktree.
-
When done:
$ git worktree remove ../project-critical-fix
Your feature worktree stayed untouched the whole time. No stashing, no conflicted git checkout, no half-applied changes.
4. Cleaning Up Old Worktrees
Over time, you’ll accumulate worktree directories. Periodically:
$ git worktree list # decide which ones are done $ git worktree remove ../project-feature-you-finished
You can also remove the directory manually after git worktree remove if Git doesn’t fully delete it (for example, if some files are write-protected).
Tips, Best Practices, and Gotchas
Tip 1: Name Directories Clearly
Use meaningful directory names so you can see at a glance what’s what:
project-mainproject-feature-paymentsproject-bugfix-login-timeout
This helps when you have several editor windows and terminals open.
Tip 2: Watch for Shared Build Artifacts
Worktrees share Git history, but not build artifacts. That’s usually good, but:
- On very large projects, repeated installs/builds per worktree can still be expensive.
- Consider configuring shared caches (e.g., a global
node_modulescache, build caches) if your tooling supports it.
Tip 3: Don’t Reuse the Same Branch in Multiple Worktrees
Git won’t let the same branch be checked out in multiple worktrees at once by default, and that’s intentional:
- It avoids confusing states where the same branch is being modified in two places.
- If you must, you can create scratch branches per worktree (
feature/x-spike,feature/x-refactor) and merge later.
Tip 4: Use Worktrees for Code Review and Bisecting
Common power-user patterns:
- Code review: Checkout the PR branch in a new worktree to test locally without disrupting your main work.
- Bisecting: Run
git bisectin a dedicated worktree so your main tree isn’t littered with temporary checkouts.
Tip 5: Learn the Shortcuts
You don’t have to memorize everything at once. Start with:
git worktree listgit worktree add ../path branchgit worktree remove ../path
Master those, and you’ll already feel a big productivity boost.
Conclusion: A Safety Net You’ll Actually Use
Git worktrees are a small feature with huge impact, especially on big, slow-to-build, mission-critical codebases. They give you:
- Multiple parallel workspaces without multiple clones.
- Isolated experiments without risky stashes.
- Quick context switching without branch gymnastics.
Most teams never move beyond git checkout and git stash, but once you adopt worktrees, you’ll wonder how you lived without them.
Next time you’re about to stash a half-finished change or clone the repo yet again, stop and try this instead:
cd /path/to/your/project git worktree add ../project-new-task origin/main cd ../project-new-task
That one command might become your new safety net for fearless experimentation.