Developer Tools & Productivity9 MIN READ

Git worktree beats stash for parallel hotfixes

A production alert fires at 4:52 PM on a Friday. You're three hours into a feature branch with uncommitted changes scattered across twelve files. The standard move is `git stash`, checkout main, branc

Potted plant with multiple stems at different growth stages branching from one root system, main trunk undisturbed.
FIG. 01  /  Developer Tools & Productivity
In this piece

A production alert fires at 4:52 PM on a Friday. You're three hours into a feature branch with uncommitted changes scattered across twelve files. The standard move is git stash, checkout main, branch off for the hotfix, fix it, deploy, then come back and git stash pop. That workflow works, until it doesn't. Git worktree offers a different path, and once you understand git worktree vs stash in a real incident, stash starts to look like the wrong default.

This isn't a theoretical debate. It's about what happens to your working directory, your build cache, and your mental state when a fix needs to ship in the next ten minutes.

The Hotfix Scenario: Why Stash Fails Under Pressure

Here's what actually happens during a stash-based hotfix. You run git stash, which bundles your uncommitted changes into a hidden commit-like object. Your working directory resets to match HEAD.

Then you checkout main, pull the latest changes, and branch off into something like hotfix/payment-timeout. You make your fix, test it, commit, and push. Now you need to get back to where you were.

You checkout your original feature branch and run git stash pop. If nothing changed in the files you'd modified, this works cleanly. If anything overlaps, you get a merge conflict inside the stash application itself.

According to the deep dive on Git Worktrees published on ideia.me, stash pop operations with conflicts can leave the working tree in a corrupted state. You're now resolving conflicts in a stash, which is a strange and unforgiving place to do it. There's no branch history to reference, no clean diff, just a flattened set of changes fighting with your current files.

The problem compounds with compiled languages. If you're running a Rust, Go, or Java project, switching branches often invalidates your build cache. According to a Stack Overflow discussion on git-worktree, compiled language workflows require full recompilation when unstashing, which adds real time overhead on top of the mental overhead of context switching.

And if the hotfix takes longer than expected, which it often does, you might need to stash again on top of an existing stash. Now you've got stash@{0} and stash@{1}, and remembering which one belongs to which task becomes its own small nightmare.

According to the same source, stash functions fine for quick one-minute branch switches but deteriorates when context switching takes longer, involves multiple stashes, or creates conflicts. A hotfix under pressure is exactly the scenario where all three of those conditions show up at once.

How Worktrees Solve Parallel Development Without Juggling

Git worktree takes a different approach. Instead of stashing changes and switching branches inside one working directory, it lets you check out multiple branches at the same time, each in its own folder, all connected to the same repository.

According to Ilango's Blog, git worktree allows checking out multiple branches simultaneously from a single repository, each with an independent working directory. Your feature branch stays exactly as you left it, untouched, uncommitted changes and all, in its own folder.

The key conceptual shift is that a worktree and a branch are not the same thing. According to the deep dive on ideia.me, a worktree and branch are independent objects, and the worktree is simply a checkout location. You can have one branch checked out in your main worktree and a completely different branch checked out in a second folder, both pointing back to the same .git directory.

This means the hotfix doesn't require you to leave your feature branch at all. You create a new worktree, do the fix there, and your original working directory never resets.

Real-World Hotfix Workflow: Step-by-Step with Worktrees

Here's how the same 4:52 PM scenario plays out with worktrees already set up as your default habit.

Your main repository lives at ~/projects/app. You're deep in a feature branch there. The alert comes in.

bash
# From inside your main repo, create a new worktree for the hotfix
git worktree add ../app-hotfix main

# Move into the new worktree
cd ../app-hotfix

# Pull latest changes just in case
git pull origin main

# Create your hotfix branch inside this worktree
git checkout -b hotfix/payment-timeout

Your feature branch work, sitting in ~/projects/app, is completely undisturbed. No stash, no reset, no risk.

You make the fix, test it, and commit.

bash
git add .
git commit -m "Fix payment timeout on retry logic"
git push origin hotfix/payment-timeout

Open your pull request, get it merged, deploy. Then clean up the worktree you no longer need.

bash
cd ../app
git worktree remove ../app-hotfix

Your feature branch is exactly as you left it. No pop, no conflict resolution, no wondering which stash entry belongs to which task. You just switch terminal tabs back to your original folder and keep working.

For teams that want a worktree detached from any branch exclusivity rules, there's a flag worth knowing. According to OpenReplay's explainer on worktrees, the -d flag creates a detached HEAD state in new worktrees, which prevents branch exclusivity restrictions that would otherwise block checking out a branch already active elsewhere.

Performance Impact: Compilation, Caching, and Build Times

The speed difference shows up most clearly in projects with heavy build tooling. Node projects with large node_modules directories, Rust projects with incremental compilation, and Java projects with long Gradle builds all suffer under the stash-and-switch model.

According to the dev.to breakdown of git worktree as a stash replacement, each worktree maintains its own node_modules, build caches, and running processes without conflicts or requiring rebuilds. That means your hotfix worktree can have a completely separate dependency install from your feature worktree, and neither interferes with the other.

This also means you can leave a dev server running in your feature worktree while a second terminal, pointed at the hotfix worktree, runs its own server on a different port. No killing processes, no restarting watchers, no waiting for webpack to recompile from scratch.

Performance Impact: Compilation, Caching, and Build Times
Workflow stepStashWorktree
Switch to hotfixStash changes, checkout branchCreate new folder, no checkout needed
Build cacheOften invalidatedIsolated, stays warm
Risk of conflict*On stash popNone, nothing to pop
Running dev serverMust stop and restartCan run in parallel
Returning to feature workPop stash, resolve conflictsSwitch terminal folder

This shows why a hotfix under time pressure favors worktrees once build caches and running processes are part of the picture.

According to OpenReplay, worktrees tend to pay for themselves within the first week for developers who experience regular interruptions with uncommitted work, especially when branch switches trigger dependency reinstalls or language-server reindexing. If your editor's language server has to reindex every time you switch branches, that cost alone can justify the switch.

When Stash Still Makes Sense

Worktrees aren't a universal replacement, and pretending otherwise would be dishonest. Stash still earns its place in a few specific situations.

  • Genuinely quick switches. If you need to check something on main for thirty seconds and come right back, stash is faster than setting up a new folder.
  • Single small file changes. Stashing one or two lines in one file rarely causes conflict problems, since there's nothing substantial to collide with.
  • Disk space constraints. Each worktree duplicates the working directory on disk, though it shares the underlying git objects. On a large monorepo with limited disk space, that duplication adds up.
  • Unfamiliar team environments. If your whole team only knows stash and you're the only one using worktrees, you may create confusion during code review or pairing sessions.

The common advice across git workflow discussions is consistent here. Stash works fine for quick, temporary switches, but worktrees are better suited for anything involving parallel branches, multiple concurrent tasks, or git context switching that takes more than a couple of minutes.

Process: How long is the switch?, then Single small file?, then Parallel work needed?, then Disk space available?, then Use stash or worktreeFIGURE 1 / PROCESSStash or worktree for this switch?How long is the switch?Thirty seconds or lessMore than a couple minutesQuick switch aheadSingle small file?One or two lines in one fileMultiple files or branchesCheck file scopeParallel work needed?Running dev servers or hotfixJust a quick temporary switchParallel work neededDisk space available?Limited space on diskAdequate space for duplicationSpace constraints matterUse stash or worktreeStash works fine hereWorktrees are better suited
A quick thirty second check determines whether stash or worktree fits your situation better.

Setting Up Your First Worktree for Emergency Fixes

Getting started doesn't require restructuring your whole repo. A few commands and a folder naming convention are enough to start.

bash
# List existing worktrees
git worktree list

# Add a new worktree tied to an existing remote branch
git worktree add ../app-bugfix-123 bugfix/123

# Add a worktree with a brand new branch
git worktree add -b feature/new-dashboard ../app-dashboard main

A sensible convention is to keep all worktrees as sibling folders to your main repo, named after the branch or ticket they represent. That keeps things scannable in your file explorer or terminal tab list.

bash
# Folder layout example
~/projects/app            # main working directory
~/projects/app-hotfix      # emergency fixes
~/projects/app-feature-x   # long-running feature work

Many developers also keep a dedicated worktree just for documentation changes, separate from active code work. According to a discussion on r/git, developers report using separate worktrees for documentation branches while maintaining code in the primary working directory, which avoids polluting a feature branch's working tree with unrelated doc edits.

Team Adoption and Worktree Maintenance

Rolling this out across a team works best as an opt-in habit rather than a mandate. Share the worktree commands in your onboarding docs, but let individual developers decide when a stash is enough and when a worktree workflow for parallel git branches makes more sense.

For cleanup, treat worktrees the same way you'd treat a finished branch: delete it once the work merges.

bash
# Remove a worktree after the branch is merged and deployed
git worktree remove ../app-hotfix

# Prune references to worktrees whose folders were deleted manually
git worktree prune

A simple checklist helps keep things tidy, especially once a team has several engineers each running multiple worktrees.

Multiple worktrees also eliminate a pattern a lot of teams fall into by default: keeping separate full clones of the same repository for different tasks. According to the OpenReplay explainer on worktrees, they remove the need to maintain separate repository clones for parallel work, since every worktree shares the same underlying git history and remote configuration.

FAQ

Q: Does git worktree work with monorepos?

A: Yes, though disk space becomes a bigger factor since each worktree checks out the full working directory. For very large monorepos, keep an eye on how many worktrees you maintain at once, and prune unused ones regularly.

Q: Can two worktrees have the same branch checked out at the same time?

A: No, Git blocks a branch from being checked out in two worktrees simultaneously by default. Using the detached HEAD flag gets around this if you just need a snapshot without active branch tracking.

Q: Do git hooks run differently across multiple worktrees?

A: Hooks are stored in the shared .git directory by default, so the same hooks apply across all worktrees of a repository. This is worth knowing if a hook assumes a specific working directory path.

Q: Is the disk overhead of worktrees a real concern?

A: It depends on repository size. Git objects are shared between worktrees, so you're mainly paying for the working directory files themselves, not a full duplicate .git history.

Takeaways

  • Use worktrees for anything longer than a quick check, especially hotfixes under time pressure.
  • Keep stash around for genuinely short, low-risk switches where setting up a folder is overkill.
  • Name worktree folders after the branch or ticket to keep a multi-worktree setup scannable.
  • Always run git worktree remove and git worktree prune as part of your git hotfix workflow cleanup, not just a manual folder delete.
  • If your build cache or dev server resets every time you switch branches, that's the clearest sign worktrees will save real time.

Sources

Researched from the following. Figures and claims were current when this piece was written and may have moved since.

  1. Ilango's Blogilango.hashnode.dev
  2. Git Worktrees: What They Actually Are and Why They Beat Stashingideia.me
  3. Git worktree: the stash replacement nobody teaches youdev.to
  4. What would I use git-worktree for?stackoverflow.com
  5. Git Worktrees Explained: When and Why to Use Themblog.openreplay.com
  6. r/git on Reddit: Started using git worktree to avoid stashing all the timereddit.com

Comments

Comments are read before they appear. No account, no email.