LEARN · PHASE 16 · LESSON 110

Isolation Without a Commit Is Not a Backup

You can tell "the agent's work is isolated" apart from "the agent's work is

Type
Learn
Prerequisites
Phase 02 (Lessons 12 and 16), Phase 11
Time
~30 minutes

Learning Objectives

  • Detect an empty agent branch whose folder still holds uncommitted work
  • Explain why git worktree remove destroys work that git reflog cannot recover
  • Add a commit instruction to an agent so its branch is never left empty
  • Write the two-command check to run before merging any agent branch

The Problem

Three agents ran in three worktrees. Each produced complete, correct work. Each reported success in a clean, confident summary.

You go to merge. You list the branches:

git branch --all
#   main
# * worktree-refactor-a
#   worktree-refactor-b
#   worktree-refactor-c

Every worktree branch points at main. Every one is empty — no commits of its own. The folders are full of edits. The branches have nothing to merge.

This is not hypothetical. It happened building this course. Three agents did perfect work and left three folders nobody could merge, because none of them committed. When those worktrees were eventually swept or removed, the edits went with them.

The agents did not fail. They did exactly what they were asked — edit the files and report. Nobody asked them to commit, so nobody's work was ever recorded.


The Concept

A worktree is a folder plus a branch label. That is the whole machine.

flowchart LR
    subgraph WT[worktree-refactor-a]
        F[folder: files edited, not committed]
        L[branch label: still at main]
    end
    F -.->|"git commit moves the label"| L
    L -.->|"no commit: label never moved"| M[main]
    style L stroke-dasharray: 5 5
Mermaid source — renders as a diagram where mermaid.js is available

Editing a file changes the folder. Only git commit moves the label. In an untouched worktree the label sits exactly where the base was — usually main. So an agent can edit every file for an hour and the repository still sees a branch identical to main.

Isolation protects against collision. It does not protect against loss. The worktree still obeys the oldest git rule in the course: uncommitted changes live only in the folder they are in. Remove the folder, lose the changes.

Why it is silent

Two things make this failure invisible until it is too late:

  • The agent's report is about files, not commits. "I refactored the parser and ran the tests" is true whether or not anything was committed.
  • Nothing errors. Git is perfectly happy to hold uncommitted work. There is no warning that a branch is empty, because an empty branch is a normal state.

The check that would have caught it

From the main checkout, before merging anything:

git log --oneline main..worktree-refactor-a    # empty output = nothing to merge
git -C .claude/worktrees/refactor-a status --porcelain   # non-empty = real, uncommitted work

If the first is empty and the second is not, you have found the bug. That combination — empty branch, dirty folder — is the signature.

The fix is an instruction, not a tool

There is no flag that makes isolation also mean "committed." The fix is to put the rule in front of the agent:

Commit before you finish. git add -A && git commit -m "...". At minimum a

wip commit at the end of each step.

Once committed, the work is in the repository's object store — shared by every worktree — and it survives the folder's removal. From that point the branch is a normal branch you can rebase and merge (Lesson 109), and even a mistake is recoverable through the reflog (Lesson 16).

The reframe: isolation is not a backup — until the agent commits, its branch

is still pointing at main, and the folder holds work git has never recorded.


Build It

1. Make a worktree and dirty it without committing

mkdir -p ~/isolation-drill && cd ~/isolation-drill
git init
printf 'v1\n' > app.txt && git add app.txt && git commit -m "start"
git worktree add ../isolation-drill-agent -b worktree-agent
cd ../isolation-drill-agent
printf 'real work\n' >> app.txt
git status --porcelain

✅ You pass when git status --porcelain shows app.txt modified and the folder holds a real edit.

2. Show the branch is empty

From the main folder:

cd ~/isolation-drill
git log --oneline main..worktree-agent
git diff main worktree-agent

✅ You pass when both commands print nothing — the branch has no commits and no content difference, even though the folder is edited.

3. Confirm the edit is only on disk

git -C ../isolation-drill-agent status --porcelain

✅ You pass when this is non-empty while step 2 is empty. That disagreement is the empty-branch bug.

4. Remove the worktree and watch the work vanish

git worktree remove --force ../isolation-drill-agent
ls ~/isolation-drill

✅ You pass when the folder is gone and the uncommitted edit with it — git cannot merge, restore, or reflog anything that was never committed.

5. Do it again, with a commit

git worktree add ../isolation-drill-agent -b worktree-agent
cd ../isolation-drill-agent
printf 'real work\n' >> app.txt
git add -A && git commit -m "agent: real work"
cd ~/isolation-drill
git log --oneline main..worktree-agent     # now shows the commit
git worktree remove ../isolation-drill-agent
git log --oneline worktree-agent           # commit survives the folder

✅ You pass when the commit is visible after the worktree is removed — the work moved from "a folder" to "the repository."


Use It

Command / conceptWhen you reach for it
git log --oneline main..<branch>Checking a finished agent branch has commits to merge
git -C <worktree> status --porcelainSeeing uncommitted work inside a worktree
git add -A && git commitThe instruction every agent needs before it reports done
WIP commitCheap insurance before anything risky
Empty branch + dirty folderThe signature of the empty-branch bug
git worktree remove --forceDeletes uncommitted work. Know that before you run it.
git reflogRecovers committed work only. Never uncommitted work.
main..branch range"What is on the branch that is not on main" — the merge preview

Exercises

  1. Reproduce the empty-branch bug from scratch: a worktree, real edits, no commit, and a branch that still equals main. ✅ You pass when git log --oneline main..<branch> is empty while git -C <worktree> status --porcelain is not.
  1. Take the same scenario and add a two-line instruction so a second run cannot finish without committing. Verify the branch is no longer empty at the end. ✅ You pass when a run that edits files leaves the branch with at least one commit, and main..<branch> is non-empty.
  1. Write the one-line check you would run before merging any agent branch, and what its two outputs must disagree about. ✅ You pass when your check runs main..<branch> and status --porcelain, and "empty + dirty" is the failure you are looking for.

Key Terms

TermWhat people sayWhat it actually means
isolation"the work is safe"Separate folders so edits do not collide. It says nothing about whether work is recorded.
empty branch"the branch is there"A branch label pointing where it started — usually main — with no commits of its own.
uncommitted work"the agent's changes"Edits that live only in one folder. Not in the object store. Not recoverable by git.
WIP commit"a throwaway commit"A commit that moves the label. Infinitely better than a folder about to be removed.
main..branch"the diff"Commits on branch that are not on main. Empty means nothing to merge.
worktree removal"cleaning up"Deleting a folder. Uncommitted work goes with it, silently.
reflog"git's undo"Recovers committed positions. It cannot see work that was never committed.

What this lesson skipped

Automatic guardrails. A hook or a script that refuses to finish a worktree with uncommitted work is the durable fix. Building one is the Phase 16 module's job, not this lesson's — this lesson teaches why the guardrail is needed.

Recovering work that was never committed and whose folder is gone. Git cannot help. Only a filesystem undelete tool or the editor's local history can, and neither is reliable. This is the reason the rule is "commit before you finish," not "commit if you remember."

Every cleanup rule for worktrees. Which worktrees Claude Code sweeps, and how uncommitted work and unpushed commits keep them on disk, is documented on the worktrees page. Worth reading once you have felt this trap.

Checked against the Claude Code worktrees documentation in October 2026: <https://code.claude.com/docs/en/worktrees>. Behaviour and messages drift; the git rule does not.

Check yourself

4 questions. Answer before you reveal — recognising the right option is not the same as being able to produce it.

  1. An agent works in its own worktree, edits six files, runs the tests, and reports success. You check its branch with git log --oneline main..worktree-agent and get no output. The folder clearly has changes. What is the state of the branch?

    1. The branch has commits, but main already contains them
    2. The branch was never created
    3. The agent committed to main by mistake
    4. The branch label still points where it started, so it has no commits of its own — the edits are uncommitted in the folder
    Show answer

    D. The branch label still points where it started, so it has no commits of its own — the edits are uncommitted in the folder

    An empty range means the branch is where it started; the edits live only in the folder because nothing was committed. Option A is the tempting wrong answer because an empty range can also mean 'main already has it' — but that requires the commits to exist on the branch, which the dirty folder contradicts. The branch exists (you listed it), and if the agent had committed to main, main itself would show the changes.

  2. Before merging any finished agent branch, which pair of checks most directly reveals the empty-branch bug?

    1. git log --oneline main..<branch> and git -C <worktree> status --porcelain
    2. git status on main, and git branch on the worktree
    3. git worktree list and git remote -v
    4. git diff main and git tag
    Show answer

    A. git log --oneline main..<branch> and git -C <worktree> status --porcelain

    The signature is an empty commit range paired with a non-empty worktree status — nothing to merge, yet real work in the folder. Option C is the tempting wrong answer because git worktree list confirms a worktree exists, which feels like proof of work, but existence says nothing about commits. Tags and remote URLs are unrelated to whether a branch is empty.

  3. Two agents finish. Agent A committed everything before its worktree was removed; Agent B did not, and its worktree was removed by a sweep. Which work can git still recover, and with what?

    1. Both — git reflog sees all edits that ever existed on disk
    2. Only B — an agent worktree is backed up when it is swept
    3. Only A — its commit is in the shared object store; B's edits were never committed and are gone
    4. Neither — removing a worktree discards any commits it held
    Show answer

    C. Only A — its commit is in the shared object store; B's edits were never committed and are gone

    A commit is written to the shared object store and survives the folder; uncommitted edits exist only in the folder and die with it. Option A is the tempting wrong answer because reflog sounds like it records everything — but it records committed positions of refs, never uncommitted file content. Agent A's commits are not discarded by worktree removal, so option D is also false.

  4. A colleague wants a durable fix so this cannot happen again, not just a note to 'remember to commit'. Which response matches the lesson?

    1. Add a warning comment to the agent's prompt that says 'please commit soon'
    2. Add a check — a hook or script — that fails when the worktree has uncommitted work at the end of the run
    3. Disable worktrees entirely and run all agents in the main folder
    4. Increase the worktree cleanup period so nothing is ever swept
    Show answer

    B. Add a check — a hook or script — that fails when the worktree has uncommitted work at the end of the run

    A guardrail that fires on uncommitted work is the fix, because the failure is silent and the forgetting agent is the one who cannot be trusted to remember. Option A is the tempting wrong answer because a stronger instruction feels like enforcement — but prose is a request, not a check, and this is exactly the failure mode of instructions. Disabling worktrees throws away isolation, and extending cleanup only delays the loss.