Skip to content
12 min read

Your agent is probably using git worktrees

I’ve used git worktrees for years. Mostly to review a PR without blowing up my current checkout, or to keep a long-running build isolated while I hacked on something else. Useful. Not life-changing.

Then I started running coding agents on multiple tasks at once, and the work suddenly had to go somewhere. And the obvious somewheres don’t really work.

A second branch? I already have one checked out. A fresh clone of the repo for every task? Slow, wasteful, everything drifts apart the moment I fetch. git stash? Fine for one task. Not four.

That’s when worktrees stopped being a nice little trick and started feeling like the thing they were always built for.

My agents lean on them constantly now. Most of the time I don’t even see it happen.


What a worktree actually is

OK so here’s the thing. A git repo has one .git/ directory. That’s where every commit, every tree, every blob you’ve ever made lives. It’s the database.

A worktree is a separate working directory that shares that database, but has its own HEAD, its own index, its own files on disk. That’s it. That’s the whole concept.

In plain terms: multiple branches checked out at the same time, in different folders. No stashing. No “you have uncommitted changes, cannot switch branch.” Each worktree minds its own business, and the shared .git/ is the only thing tying them together.

Shared .git with three working dirs on different branches
One database, three worktrees. Each one gets its own branch, its own index, its own files.

Before you ask: yes, you could just clone the repo three times. You’d also duplicate the object database three times, wait three times as long to set them up, and watch them drift independently every time you fetch.

Or you could branch-switch in your existing checkout. Fine — until you have uncommitted changes. Or a running dev server. Or a build watcher that doesn’t know the files changed out from under it.

Worktrees sit between: one database, many working directories, cheap to create, cheap to destroy.

my-repo/              ← main worktree (contains .git/)
  .git/               ← the shared object database
  src/
../feature-x/         ← extra worktree on branch feature-x
  src/                ← fully independent working files
../bugfix-y/          ← extra worktree on branch bugfix-y
  src/

Why agents reach for them

Because isolation is the natural unit of parallel work.

Two processes can’t safely share a working directory. One agent’s git checkout is another agent’s uncommitted changes gone. One’s build output is the other’s file watcher meltdown. Give each task its own folder and most of these problems quietly go away.

Cloning for each task is the brute-force way to get that isolation. Worktrees are the elegant one.

Creating a worktree is almost free. One extra folder, one extra HEAD, one extra index. No fetch. No duplication. No drift. The object database is already there.

So the shape of a reasonable agent is short: spin up a worktree on a new branch, do the work, merge or throw it away. That’s the whole loop.

If your agent runs multiple tasks in parallel without stomping on your working copy — and mine does, constantly — this is almost certainly how.


What you give up by treating them as invisible plumbing

Here’s the part that snuck up on me. When I create a worktree, I know it exists. I picked the path. I’ll remember to clean it up. When an agent creates one, none of that is true. The tool is fine — I’ve been using it for years. What’s different now is that when the agent uses it, it all happens without me looking.

A few ways this bites:

Orphan worktrees pile up on disk. Agent crashed, got killed, forgot to clean up — doesn’t really matter why. The folder sticks around. du -sh quietly grows. git status in my main checkout doesn’t know a thing about it.

Orphan branches multiply too. I rm -rf the folder because it’s the obvious move. The branch stays. The admin entry inside .git/ stays. git branch gets longer and longer, and I start wondering where all those names came from.

pwd stops being reliable. I open a terminal inside what I think is my main checkout, run git status, and see unfamiliar changes. I’m in a worktree. Commands I run do things I didn’t expect.

Commits get forgotten. I made one in a worktree. Never merged it. The agent moved on. That commit is now reachable only from a branch I never look at, in a folder I’ve stopped opening.

None of these are the agent’s fault. The agent’s doing what I asked. The gap is that I wasn’t watching.


The four commands you actually need

Four. That’s it.

(Well — four, plus one bonus at the end. But really, four.)

git worktree add -b feature-x ../feature-x

Makes a new branch feature-x from HEAD, and sets up a new worktree at ../feature-x checked out on it. Drop the -b if the branch already exists.

Use this when you want to spin up an isolated checkout yourself. Your agent does it for you, yes. You can too.

git worktree list

Every worktree. Its path, its HEAD, its branch. If something feels off, run this first. The annotations matter — (bare), (detached HEAD), prunable all tell you something.

git worktree remove <path>

The right way to delete a worktree. Removes the folder and the admin entry git keeps inside .git/.

rm -rf is what leaves the admin entry behind. Don’t do that.

git worktree prune

For when you already did the thing I just told you not to do.

prune reaps admin entries whose folders have vanished. Safe to run whenever. Good thing to run after you’ve been sloppy.

Oh, and: git worktree add --detach <path> makes a worktree in detached-HEAD state, no new branch. Useful for a one-off diagnostic checkout. That’s the bonus.


Go break it

Here’s the whole thing in one sandbox. Add a few worktrees. Try rm -rf on one — the folder vanishes but the admin entry inside .git/worktrees/ is still there, flagged red. Run list and spot the prunable annotation. Then prune to reap it. That’s the contrast worth learning.


Agents handle worktrees fine. They really do.

But if you can’t name what they’re doing, you can’t audit the work, recover when something fails, or clean up after. So look.

Four commands.

Thanks for reading.

Say hi on LinkedIn (opens in new tab)

More writings

  1. 2026 5

    1. Your agent is probably using git worktrees
    2. So Much for O(1)
    3. We Might All Be AI Engineers Now
    4. The Hardest Bug I Ever Fixed Wasn't in Code
    5. Why I Switched to Podman (and Why You Might Too)
  2. 2024 3

    1. The World is Stochastic
    2. Debugging a running Java app in Docker
    3. Why is it UTC and not CUT?
  3. 2023 12

    1. Deep prop drilling in ReactJS
    2. Eigenvectors
    3. Java's fork/join framework
    4. TypeScript's omit and pick
    5. JavaScript's new immutable array methods
    6. Integrating JUnit 5 in Maven projects
    7. My take on ChatGPT and prompt engineering
    8. Declarative events in ReactJS
    9. Positive Lookaheads
    10. Functors
    11. Fast forward videos with ffmpeg
    12. Rotate y-axis of a 2D vector
  4. 2022 9

    1. Synchronizing time
    2. Vector rotation
    3. Sed find and replace
    4. Asgardeo try it application
    5. Flatten error constraints
    6. Good Git commit messages
    7. Asgardeo JIT user provisioning
    8. Monotonic Arrays
    9. How GOROOT and GOPATH works
  5. 2021 1

    1. Two summation