Git Worktrees · Lesson 1
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.
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 thing | What 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.
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.
This is the part worth actually holding in your head, because every worktree rule below is a consequence of it.
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.
Shared database, separate views. So git enforces one 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
Here is the anticlimax, and the real point of this lesson.
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:
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.
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.
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.
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.