Skip to content

Course · Claude Code · Sessions & context

Compare approaches with conversation branches and Git worktrees

The running example is a small Express + TypeScript payments service: routes begin in src/index.ts, payment code lives under src/payments/, and npm test runs the Vitest suite in tests/. The service registers GET /health in src/index.ts, and the health task added GET /healthz beside it. Both health addresses must return the same response: HTTP 200 with the JSON body {"status":"ok"}, with payment behavior untouched and HTTP tests for both routes in tests/health.test.ts. That sentence is the acceptance brief this page reuses. You can register the two paths together with one handler, or keep separate registrations that call a shared handler. For a small service, either might be reasonable. Before turning this into a general argument about abstraction, compare the actual changes each would require.

Start with a design-only comparison in the health session, meaning the Claude Code conversation in which that task was done. If you have no such conversation, open a session in your own repository (the install lesson covers that), ask it for one approach to a small change first, and treat that answer as the original session’s approach. Then use /branch health-shared-handler at the prompt to preserve the current conversation and continue a copy. The original remains available through /resume. The session guide describes conversation branches; the CLI equivalent is claude --continue --fork-session when resuming the most recent session.

Two conversations can still touch one file

Section titled “Two conversations can still touch one file”

Ask the branched conversation for a proposal without edits:

Compare separate health-route registrations using one shared handler
with registering both paths together. Read the current app first.
Keep both response contracts unchanged. Show the proposed patch and
what the HTTP tests would need to establish. Do not write files.

Compare that proposal with the original session’s approach. Two conversations are useful when you want to preserve their different assumptions; each keeps its own context, the information available to Claude when it decides. They are not required for every comparison, and discussing alternatives together does not inevitably confuse a model.

More importantly, /branch does not create a Git branch or a separate working directory. Separate contexts do not isolate the files either conversation can then inspect or change: if both conversations edit the same checkout, they edit the same files. Preserving the first answer will not preserve the first implementation after the second overwrites it.

Give each implementation its own working directory

Section titled “Give each implementation its own working directory”

For an implementation comparison, begin from a clean, reviewed commit from before the experimental change; if the health patch is already committed, the base is the commit before it. If the health patch is still uncommitted, preserve it first and decide which committed base the experiment should use. Do not silently omit that patch or commit failing work just to satisfy the example. Without a suitable base, keep this comparison at the proposal stage.

From the repository root, the following creates two new branches and worktrees from the same HEAD, so the repository needs at least one commit; if your copy has no history, create the baseline commit from the install lesson first. Use unused names and directories:

Terminal window
git status --short
git rev-parse HEAD
git worktree add -b health-direct ../payments-health-direct HEAD
git worktree add -b health-shared ../payments-health-shared HEAD
git worktree list

Check the status before the creation commands; this walkthrough expects it to be clean. Do not move the base branch between those commands. Git worktrees provide separate working files while sharing repository history. They are not separate machines: ports, credentials, and external services can still be shared.

Open one terminal in each worktree. Check its directory, install the project’s dependencies there if needed, and start a fresh Claude session with the same small acceptance brief from the top of this page: both routes answer HTTP 200 with the same JSON body, payment behavior is untouched, and both routes have HTTP tests. Give one the direct-registration approach and the other the shared-handler approach. Run the same HTTP checks in each - one at a time if the tests bind the same port. Neither result is established until those checks actually run.

Before committing, inspect each worktree’s status and diff, including untracked tests. git diff health-direct health-shared compares the branch tips; it will not show edits that remain uncommitted in the worktrees. That distinction matters when both branch names still point at the starting commit.

Once each result has met the project’s checks and been deliberately committed, compare them:

Terminal window
git diff health-direct health-shared -- src tests package.json

Look for the cost of the extra abstraction, the clarity of the route registrations, and whether both tests would catch a change to either response. The smallest patch is not automatically the clearest, and this lesson does not choose a winner before seeing yours.

Keep any useful experiment until you have preserved the result you want. Returning to the main session, state which implementation, if any, was selected and where it exists. A conversation saying “we chose the shared handler” should not be allowed to masquerade as a merged patch.

Comparing designs produces useful evidence and a fair amount of discussion. Next, inspect what the continuing session is carrying before deciding what to keep.