fix/login-timeout, another is building a feature on
feat/dark-mode, and a third is doing code review on a PR
branch. Right now, switching between them means stash-pop-commit-juggle โ
or cloning the repo three times. There's a better way.
You know that a normal git repository has two parts that live together:
When you git checkout feature-branch, git updates both your
working tree and the HEAD pointer inside .git/. Your
entire working tree flips to match the new branch. One working tree, one
branch at a time.
This is the single-working-tree constraint. It's why you can't have two branches checked out simultaneously in the same repo โ and it's exactly the problem worktrees solve.
A worktree is an additional working tree attached to the
same .git directory. Instead of one working tree, you have
many. Each one has its own branch checked out, its own staged changes, and
its own untracked files. But they all share one object database, one set
of refs, one history.
.git directory โ all objects, all refs, all history. A
worktree shares the same .git. Creating one is
instantaneous (no network, no copying) and they stay in sync automatically
โ a branch created in one worktree is immediately visible in all others.
Here's what a repository with two additional worktrees looks like:
Three critical observations from this diagram:
| What's shared |
The object database (.git/objects/), refs
(.git/refs/), config, hooks โ everything in the real
.git/ directory. A commit made in one worktree is
immediately reachable in all others. A branch created in one worktree
appears in git branch everywhere.
|
|---|---|
| What's isolated |
The working tree files, the index (staging area), and HEAD โ each
worktree maintains its own versions of these in
.git/worktrees/<name>/. Staged changes in one
worktree are invisible to others. You can have different files open in
different editors pointed at different worktrees.
|
| The pointer file |
Each linked worktree has a .git file (not a
directory!) that contains a single line:
gitdir: /path/to/main/.git/worktrees/name/. This is how
git knows which worktree-specific metadata to use. Run
cat .git in a linked worktree to see it.
|
Your parallel agentic coding workflow today probably looks like one of these:
# Agent 1 finishes on feat/dark-mode
git stash
git checkout fix/login-timeout
# Agent 2 works...
git checkout feat/dark-mode
git stash pop
# Fragile. One mistake and you lose work.
git clone my-project my-project-agent-2
git clone my-project my-project-agent-3
# Slow. Disk-heavy. Branches get out of sync.
# You need to git fetch in each clone to see new branches.
# Spin up a worktree for each agent in under a second:
git worktree add ../my-project-fix-login fix/login-timeout
git worktree add ../my-project-dark-mode feat/dark-mode
# Each agent gets its own directory, its own branch, its own staged state.
# All share the same .git โ no syncing needed.
# When done:
git worktree remove ../my-project-fix-login
cd into the directory and you're there.
We'll practice these properly in the next lesson. For now, here's the shape of the API so you can see how simple it is:
| Command | What it does |
|---|---|
git worktree add <path> <branch> |
Create a new worktree at path, checking out
branch
|
git worktree list |
Show all worktrees and which branch each is on |
git worktree remove <path> |
Delete a worktree (safe โ refuses if there's uncommitted work) |
git worktree prune |
Clean up metadata for worktrees whose directories were manually deleted |
If you remember nothing else from this lesson, remember these:
Everything in .git/ is shared. A
git fetch in any worktree updates refs for all worktrees.
A git branch -D in any worktree deletes the branch
everywhere. There is no per-worktree isolation at the git-database
level.
The working tree and index are private. Each worktree
has its own files on disk and its own staging area. You can have
src/app.ts open in three different editors with three
different versions, and git handles it correctly.
The .git in a linked worktree is a file, not a
directory.
This is the secret handshake. If you ever wonder "is this a main
worktree or a linked one?", run cat .git. A directory
means main worktree; a file containing gitdir: means
linked.
ls -la .git in your current repo. Now
imagine that instead of a directory, it's a single file pointing somewhere
else. That mental shift โ
.git as a pointer, not a container โ is the foundation of
worktrees. When you're ready, proceed to
Lesson 0001: Creating & Listing Worktrees
to start using them.
.git โ not a clone, not a copy.
.git file (not a
directory) that points back to the main repo's metadata.
add, list,
remove, prune.
Primary source: git-worktree official documentation. Read the DESCRIPTION section โ it's concise and well-written.
Ask questions: If anything in this lesson is unclear, ask your agent-teacher. You can say "I don't understand the pointer file" or "show me the difference between a clone and a worktree again" and I'll explain it differently.