Git Worktrees · Lesson 1

What a worktree actually is

One repository. Many directories. And the reason “putting the work back” has no special command — because it never needed one.

You already run agents in separate worktrees, and that part works. The part that doesn’t is the end: work finishes, and you aren’t sure how to get it back into main or how to clean up after. So directories accumulate.

That gap isn’t a missing command. It’s a missing model. Once you can see what a worktree is made of, the ending becomes obvious — and slightly anticlimactic. This lesson buys you the model, then makes you use it.

1Two things that were always separate

When you run git clone, you get one folder, and it feels like one thing. It is actually two things stacked in the same place:

The thingWhat it is
repository
the .git folder
The database. Every commit, every branch, all of the history. It has no opinion about which branch you happen to be looking at.
working tree
the visible files
One branch, unpacked into real files you can open and edit. A view of the database at one point in its history.

Terminology “Working tree”, “working directory”, and “checkout” all get used for this in the wild. The git docs say working tree. Use that word — it is the one that makes worktree stop looking like jargon.

Normally you get exactly one working tree, so git checkout has to rewrite it in place to show you a different branch. That is the swap that makes context-switching hurt, and it is why two agents in one folder fight: they are both editing the same single view.

The whole idea

A worktree is an additional working tree attached to the same repository. One database, several views open at once. Nothing is copied, nothing is cloned, and no history is duplicated.

2What’s shared, what isn’t

This is the part worth actually holding in your head, because every worktree rule below is a consequence of it.

app/.git the repository — one copy all commits · all branches · remotes · stash SHARED BY EVERYTHING BELOW app/ MAIN WORKTREE on branch main its own HEAD + index its own files on disk agent-alpha/ LINKED WORKTREE on branch agent-alpha its own HEAD + index its own files on disk agent-beta/ LINKED WORKTREE on branch agent-beta its own HEAD + index its own files on disk
Three working trees, one repository. The arrows are not copies — they are pointers.

Two consequences fall straight out of that picture, and they are the two that matter most to you:

Because the database is shared — the moment an agent commits in agent-alpha/, that commit already exists in the one shared repository. It is not stranded in that folder. It is not somewhere else that needs fetching. From app/ you can already see it. The work has, in a real sense, already arrived; all that’s left is pointing main at it.

Because each working tree has its own HEAD — the pointer naming the branch this directory is on — each worktree can sit on a different branch, and agents never overwrite each other’s files. That is the isolation you’re already relying on.

HEAD A tiny file holding the name of the branch you’re currently on. “Which branch am I on?” is answered per-worktree, which is exactly why worktrees work.

3The one rule that generates the errors

Shared database, separate views. So git enforces one rule:

The rule

A branch can be checked out in only one worktree at a time.

If two directories were both on main, two sets of edits would claim the same branch, and one would have to lose. Git refuses instead. Both errors you can hit are this same rule wearing different clothes:

git checkout agent-alpha
fatal: 'agent-alpha' is already used by worktree at
       /Users/you/code/agent-alpha

git worktree add ../dupe agent-alpha
Preparing worktree (checking out 'agent-alpha')
fatal: 'agent-alpha' is already used by worktree at
       /Users/you/code/agent-alpha

Read either one as: that branch is spoken for — go to the directory that already has it. Git even tells you which directory. It is not a problem to solve; it is a signpost.

You can see the same rule marked in your branch list. The + means “checked out in a different worktree”, exactly as * means “checked out here”:

git branch
+ agent-alpha
* main

4So how do you put the work back?

Here is the anticlimax, and the real point of this lesson.

There is no put-back command

There is no git worktree merge, no git worktree finish, no git worktree land. Landing a worktree’s work is an ordinary merge of an ordinary branch — or an ordinary pull request. Worktrees changed where you stand. They changed nothing about how branches combine.

You were likely looking for a worktree-shaped ending to a worktree-shaped workflow. There isn’t one — because from the repository’s point of view, agent-alpha is just a branch. It always was. The worktree was only ever a second window onto it.

Which leaves exactly one thing that’s genuinely new, and it’s the thing worth burning in:

The one new burden

Which directory you are standing in now matters. git merge merges into the branch of the worktree you are currently in. To land work into main, you must be standing in the worktree that has main checked out — normally your original clone.

Standing in the wrong directory is, quietly, the most likely reason this felt broken. Running git merge main from inside agent-alpha/ is a perfectly valid command that does the opposite of what you want — it pulls main’s work into the agent’s branch. Git will not stop you. It has no way to know you meant the reverse.

So the shape of the ending is: go to the main worktree, merge the branch, then tear down. That’s it.

# from app/ — the worktree that has main checked out
git merge agent-alpha
Updating b957f75..2af529e
Fast-forward
 feature.txt | 1 +

You’ll drill the full teardown — and the two ways it goes wrong — in Lesson 2. For now, the win is the model.

5Practice — recall, don’t recognise

Scroll back only if you’re stuck. Getting one wrong and then reasoning it out is worth more to your long-term memory than getting it right by looking.

6Do it for real — ten minutes

The model isn’t yours until your hands have run it once. This is a throwaway repo, so nothing you do here can hurt anything.

# 1. a scratch repo with one commit
cd /tmp && rm -rf wt-practice && mkdir wt-practice && cd wt-practice
git init -b main app && cd app
echo "# App" > README.md && git add -A && git commit -m "init"

# 2. add a worktree. no branch named -> git names it after the folder
git worktree add ../agent-alpha

# 3. LOOK. this is the picture from section 2, on your disk.
git worktree list
cat ../agent-alpha/.git
git branch

Stop at step 3 and read the output properly. ../agent-alpha/.git is a file, not a folder — a one-line signpost reading gitdir: … that points back to the one real repository. That single line is the arrow in the diagram. And git branch should show the + from section 3.

Why this matters Seeing that .git is a pointer file is the moment worktrees stop being magic. There is only ever one repository.

# 4. work in the other tree, as an agent would
cd ../agent-alpha
echo "feature" > feature.txt && git add -A && git commit -m "add feature"

# 5. the payoff: go to the main worktree and look for that commit
cd ../app
git log --oneline --all

Your commit is listed — from a directory where feature.txt does not exist on disk. Nothing was pushed, fetched or copied. That is “shared database, separate views” in one screen, and it is the fact that makes landing work trivial.

# 6. land it — standing in app/, on main
git branch --show-current   # confirm: main. always confirm.
git merge agent-alpha
ls                              # feature.txt is here now

Make git branch --show-current a reflex before any merge. It is the one-second check against the mistake this workflow invites.

7Read the source

Your primary source for everything in this lesson — and the page to return to rather than a blog post:

git-worktree — Official Git Reference
Read the DESCRIPTION section only, about eight paragraphs. It states the main/linked worktree split and the shared-except-HEAD-and-index rule in the docs’ own words — worth seeing after meeting the idea here. Everything below DESCRIPTION is per-command detail; skip it for now.

Full annotated source list: RESOURCES.md.

Ask your teacher. I’m your teacher for this, not just the author of the page — if any of it is fuzzy, say so and we’ll go again from a different angle. Especially worth asking: “what’s the difference between HEAD and a branch?”, “what actually happens if I merge from the wrong directory?”, or “show me what my real worktrees look like right now.” That last one is a good one — we can point this at your actual repository.