Lesson 0001: Creating & Listing Worktrees

Part of Git Worktrees for Parallel Agentic Coding  |  ~15 minute read + practice

You've seen the diagram. Now build it. In this lesson you'll create your first worktree, inspect every file it creates, and verify with your own eyes what's shared and what's isolated. By the end, git worktree list will feel as natural as git branch.

Your First Worktree

Open a terminal in any git repository โ€” your current project is perfect. We'll create a worktree for a new branch called experiment/lesson-0001.

# From the root of your repo:
git worktree add ../my-project-lesson-0001 -b experiment/lesson-0001

That's it. You now have a second working tree. Let's break down what just happened.

The command git worktree add <path> -b <branch> does three things simultaneously:

  1. Creates a new branch (experiment/lesson-0001) at the same commit as your current HEAD
  2. Creates a new directory at the path you specified, with that branch checked out
  3. Registers the worktree metadata in .git/worktrees/ so git knows it exists

If the branch already exists, omit -b:

git worktree add ../path/to/worktree existing-branch

Inspecting What You Made

Let's examine the result piece by piece. Run each command and compare what you see to the explanation below.

1. List all worktrees

git worktree list

You'll see output like:

/Users/mark/dev/my-project                  abc1234 [main]
/Users/mark/dev/my-project-lesson-0001      abc1234 [experiment/lesson-0001]

Each line shows: path, commit hash, branch name (in brackets). The first line is your main worktree โ€” the original one. The second is your new linked worktree. Both are at the same commit because -b branched from HEAD.

git worktree list is your dashboard. Run it whenever you need to orient yourself. It answers "what worktrees exist, where are they, and what branch is each on?" in one line. Make it a habit.

2. Examine the .git difference

# In your MAIN worktree:
ls -la .git
# Output: a directory full of subdirectories (objects/, refs/, etc.)

# In the NEW worktree:
ls -la ../my-project-lesson-0001/.git
# Output: a single FILE, not a directory

cat ../my-project-lesson-0001/.git
# Output: gitdir: /Users/mark/dev/my-project/.git/worktrees/my-project-lesson-0001

This is the secret handshake from Lesson 0000 made concrete. The linked worktree's .git is a pointer file, not a directory. It tells git: "your real metadata lives over there, in the main repo's .git/worktrees/."

3. Examine the worktree metadata

ls -la .git/worktrees/my-project-lesson-0001/
# Output: HEAD  ORIG_HEAD  commondir  gitdir  index  logs/

This directory is the linked worktree's private git state. Let's look at each file:

File What it holds
HEAD Which branch/commit is checked out in this worktree
ORIG_HEAD The previous HEAD (used by git reset, merge conflict recovery)
index The staging area โ€” what's currently staged in this worktree
commondir Path back to the main .git/ directory (one level up from worktrees/)
gitdir Path to this metadata directory (self-referential)
logs/ HEAD reflog for this worktree (separate from the main worktree's reflog)
Each worktree gets its own index and its own HEAD reflog. This is why staged changes in one worktree don't leak into another โ€” the index is stored per-worktree. And the separate reflog means git reflog in a linked worktree only shows that worktree's history, not the whole repo's.

What Gets Shared: Prove It To Yourself

The mental model says the object database and refs are shared. Let's verify.

# In the MAIN worktree:
echo "hello from main" >> shared-test.txt
git add shared-test.txt
git commit -m "add shared-test from main worktree"

# Now switch to the LINKED worktree:
cd ../my-project-lesson-0001
git log --oneline -3
# You'll see the new commit immediately โ€” no fetch needed.

# The branch you created also appears everywhere:
git branch --list 'experiment/*'
# Shows experiment/lesson-0001 in both worktrees.

No git fetch. No git pull. The commit is visible immediately because all worktrees share the same .git/objects/ and .git/refs/.

What Gets Isolated: Prove It To Yourself

# In the LINKED worktree:
echo "staged in linked worktree" >> isolation-test.txt
git add isolation-test.txt
git status
# Shows isolation-test.txt as staged

# In the MAIN worktree:
cd ../my-project
git status
# Shows nothing about isolation-test.txt โ€” it's invisible here.

The staging area (index) is per-worktree. Untracked files are also per-worktree โ€” each worktree has its own set of files on disk. This is the isolation you need for parallel work.

Removing a Worktree

When you're done with a worktree, clean it up properly:

# The safe way โ€” refuses if there's uncommitted work:
git worktree remove ../my-project-lesson-0001

# Force removal (discards uncommitted changes):
git worktree remove --force ../my-project-lesson-0001

# Verify it's gone:
git worktree list
Never delete a worktree directory with rm -rf. If you manually delete the directory, git still has metadata in .git/worktrees/ โ€” and git worktree list will show a "prunable" entry. Use git worktree prune to clean those up, or better yet, always use git worktree remove.

Quick Reference: The Core Commands

Command What it does
git worktree add <path> <branch> Create a worktree at path with branch checked out
git worktree add -b <new-branch> <path> Create a worktree AND a new branch simultaneously
git worktree add --detach <path> <commit> Create a worktree in detached HEAD at a specific commit
git worktree list Show all worktrees with path, commit, and branch
git worktree list --porcelain Machine-readable format (useful for scripts)
git worktree remove <path> Safely remove a worktree (refuses if dirty)
git worktree remove --force <path> Remove a worktree even if it has uncommitted changes
git worktree prune Clean up metadata for worktrees whose directories were deleted

Check Your Understanding

Quiz: What happens in each scenario?

  1. You run git commit in a linked worktree. Does the commit appear in git log in the main worktree?

    Think about it, then click to reveal.

    Answer
    Yes โ€” immediately. Commits go into the shared .git/objects/ database and the branch ref is updated in the shared .git/refs/. All worktrees see the new commit instantly.
  2. You run git add in a linked worktree. Does git status in the main worktree show the staged file?

    Think about it, then click to reveal.

    Answer
    No. The index (staging area) is stored per-worktree in .git/worktrees/<name>/index. Each worktree has its own staging area.
  3. You run git branch -D experiment/lesson-0001 in the main worktree while the linked worktree still has that branch checked out. What happens?

    Think about it, then click to reveal.

    Answer
    Git refuses. You cannot delete a branch that is checked out in any worktree. You must remove the worktree first (git worktree remove), which also handles the branch cleanup.

Recap

Primary source: git-worktree โ€” COMMANDS section. The add, list, remove, and prune subcommands are documented here with all flags.

Ask questions: If the isolation model isn't clear, ask your agent-teacher to walk through a specific scenario โ€” e.g., "What happens if I rebase in worktree A while worktree B has the old version of the branch checked out?"