You’re three files into a feature branch, nothing committed, when a teammate pings you about a null-pointer crash in production. The usual move is git stash, check out main, fix it, push, then git stash pop and hope nothing in your half-finished feature depended on the files you switched away from. git worktree skips the shuffle. It checks out the hotfix branch into a second folder, next to your feature branch, with both backed by the same repository.

What git worktree actually does

A normal checkout gives you one branch’s files at a time. Switching branches rewrites those files in place. git worktree gives you several checkouts of the same repository, each in its own directory with its own branch, and you can edit them independently.

They’re not separate clones. There’s exactly one .git directory holding the object database, the refs and the config, and every worktree reads and writes to it. In a secondary worktree, .git isn’t even a directory: it’s a one-line file pointing back to the shared one. That’s why creating a worktree is close to instant and adds no history on disk.

One restriction matters. Two worktrees can’t have the same branch checked out at once, because a branch points at one current commit and two checkouts committing to it would fight over that pointer. Everything else is per-worktree, from untracked files and the index down to which commit HEAD sits on.

How to create a worktree for a hotfix

From inside your existing checkout of myapp, on feature/checkout-flow with uncommitted changes:

1
git worktree add ../myapp-hotfix -b hotfix/null-pointer main

This creates ../myapp-hotfix next to your current directory, with a new branch hotfix/null-pointer created from main and checked out inside it. Your original directory stays on feature/checkout-flow, dirty and untouched.

1
2
3
4
cd ../myapp-hotfix
# fix the bug, commit, push
git push -u origin hotfix/null-pointer
cd ../myapp

Back in the original directory, your feature work is exactly as you left it. Nothing to pop, and no stash to forget about.

Without -b, git worktree add <path> names the branch after the last component of the path. If no branch by that name exists, Git creates it from HEAD; if it exists and isn’t checked out in another worktree, Git checks it out. Use -d (--detach) when you want a commit to poke around in with no branch at all.

How to list, remove and prune worktrees

1
git worktree list
1
2
/home/user/myapp          3a1f9c2 [feature/checkout-flow]
/home/user/myapp-hotfix   7e04d81 [hotfix/null-pointer]

Once the hotfix is merged, remove the worktree through Git rather than deleting the folder:

1
git worktree remove ../myapp-hotfix

remove refuses if the worktree has modified tracked files or untracked files. Pass -f to override. If the directory disappears some other way (a stray rm -rf, a crashed CI job), Git keeps its administrative entry and git worktree list still shows it. Clear the stale entry with:

1
git worktree prune

Run it with -n first to see what it would remove.

Some worktrees should stick around for weeks: a long-running release branch, or a checkout on a network share that isn’t always mounted. Lock those so prune leaves their entry alone and move and remove refuse to touch them:

1
2
git worktree lock --reason "release branch, do not prune" ../myapp-release
git worktree unlock ../myapp-release

Unlock first if you want to relocate one with git worktree move <path> <new-path>. Moving or removing a locked worktree without unlocking takes --force twice, which is meant as a deliberate override.

When to use git worktree besides hotfixes

Any time you need two live checkouts instead of one:

  • Reviewing a PR without losing your place. git worktree add ../myapp-review origin/some-pr-branch gives you a buildable copy of someone else’s branch while your own work stays checked out where it was.
  • Running git bisect without blocking everything else. A bisect moves HEAD on every step, so the checkout it runs in is unusable for anything else until you finish or reset. Run it in a dedicated worktree (see How to Use Git Bisect to Find a Broken Commit) and keep working in your main one.
  • Running two jobs against the repo in parallel. A long test suite on one branch while you edit another, or two AI coding agents on separate tasks: each needs its own working directory. A worktree provides one without a second git clone and a second multi-gigabyte .git folder.

When not to use git worktree

Each worktree duplicates the working tree, not the object database. Ten worktrees of a repo with a 50 MB checkout cost roughly 500 MB of files on disk, even with one .git. For a five-minute context switch, git stash is cheaper and leaves nothing to clean up.

Submodules are the sharp edge. git worktree move won’t move a worktree that contains submodules, and a new worktree starts with its submodule directories empty until you run git submodule update --init inside it. The Git docs themselves call submodule support in multiple checkouts incomplete, so for a superproject with many submodules a separate clone is the safer choice.

Some tooling also assumes one working directory per repository. An IDE or file-watcher that keys its cache off the absolute repo path can get confused by the same history in two places. Opening each worktree as its own project, not as a subfolder of the first, usually fixes it.

If you only need to shelve or undo something in the checkout you already have, git stash or git reset, revert, or restore is the lighter tool. The next time a hotfix lands mid-feature, try git worktree add before git stash and see which one you’d rather clean up after.