DEV Community

Cover image for Testing Microservice Changes from Git Worktrees End to End Without the Terminal Tab Explosion
Jan van Dorth
Jan van Dorth

Posted on

Testing Microservice Changes from Git Worktrees End to End Without the Terminal Tab Explosion

TLDR: made a visual cli-tool called Recomposable to tackle this issue.

If you use Claude Code with git worktrees, you probably have multiple branches of the same repository checked out simultaneously. Claude works in one worktree, you review in another. This works well for single-service projects, but it breaks down when you run microservices.

The problem: you need to verify that the changes Claude made to one service still work with the rest of your stack. This means rebuilding that one service from the worktree's code while keeping everything else on main, and Docker Compose has no concept of worktrees, it only knows about files on disk, so you're on your own. I have solved this for myself with the cli-tool Recomposable, which I will discuss further down the page.

What you have to do today

Say Claude Code is working on your auth-service in a worktree, and you want to test its changes against the rest of your stack. Here's the manual workflow:

Step 1: Find the worktree path.

Claude Code creates worktrees in .claude/worktrees/ with generated names, so you need to find it first.

git worktree list
# /Users/you/project                   abc1234 [main]
# /Users/you/project/.claude/worktrees/jan-abc123  def5678 [fix-oauth]
Enter fullscreen mode Exit fullscreen mode

Step 2: Build the service from the worktree.

You need to combine the worktree path with the compose file path, specify the service, and build:

docker compose -f /Users/you/project/.claude/worktrees/jan-abc123/docker-compose.yml build auth-service
Enter fullscreen mode Exit fullscreen mode

Step 3: Start it.

docker compose -f /Users/you/project/.claude/worktrees/jan-abc123/docker-compose.yml up -d auth-service
Enter fullscreen mode Exit fullscreen mode

Step 4: Verify.

Open another tab, tail the logs, check the other services, maybe rebuild if it failed.

Step 5: Switch back.

When you're done testing, repeat steps 2-3 but pointing back at the original compose file.

Every step requires you to remember or paste the worktree path, and if you have multiple compose files you also need the correct file name. There's no overview of which services are running code from which branch - you just have to remember.

You can script this with aliases or a Makefile target, but you still lack a way to see at a glance which service is running from which worktree, and every new worktree means updating your aliases.

What recomposable does instead

recomposable is a Docker Compose TUI I built for development workflows, and version 1.1.4 adds worktree switching as a first-class feature.

Press t on any service, and a picker shows all available git worktrees. Select one with j/k and Enter, and the service is stopped, rebuilt from the target worktree's compose file, and started. That's it.

When services run from different branches, a WORKTREE column appears automatically with non-main branches highlighted in yellow, so you see at a glance which service runs from which branch.

SERVICE              STATUS    BUILT     PORTS          WORKTREE
auth-service         running   2m ago    5001           fix-oauth
api-gateway          running   1h ago    8080           main
web-app              running   3d ago    3000           main
Enter fullscreen mode Exit fullscreen mode

No paths to remember, no compose file flags, no switching terminals to check which branch a container was built from.

How it works

When you press t, recomposable runs git worktree list --porcelain from the compose file's directory to discover all worktrees, and the picker shows each worktree's branch name and path.

On selection, it maps the compose file path to the equivalent path in the target worktree. If your compose file is at infra/docker-compose.yml relative to the git root, it looks for the same relative path in the target worktree and shows an error if the file doesn't exist or the service isn't defined in the target compose file.

The override is stored per service, and all subsequent operations — rebuild, restart, logs, exec, watch, dependency-aware cascade rebuild — automatically use the overridden compose file. Switching back is the same action: press t and select the original worktree.

The Claude Code workflow

This is the workflow I built the feature for:

  1. Start recomposable in your project directory, with your full stack running on main.
  2. Open Claude Code and tell it to work on auth-service in a worktree.
  3. Claude makes its changes, and you want to verify them end-to-end.
  4. In recomposable, navigate to auth-service, press t, and select the worktree Claude is working in.
  5. The service rebuilds from Claude's branch while the rest of the stack stays on main.
  6. Check logs, run requests, and verify — if something is wrong, check the logs right there in the TUI.
  7. When done, press t again and switch back to main.

No terminal tabs, no path juggling, no guessing which branch is running.

This scales to any number of services. Claude working on three services across two worktrees? Switch all three, and the WORKTREE column shows you exactly what's running where.

Future work

The worktree feature covers the core workflow, but there are gaps worth addressing for teams that use this pattern heavily:

Auto-detect worktree changes. Currently you manually press t to switch, but recomposable could watch for new worktrees appearing (e.g., Claude Code just created one) and prompt you to switch the affected service, removing the "go check if Claude is done, then switch" polling loop.

Worktree-aware cascading rebuilds. The dependency-aware rebuild (d) already restarts transitive dependents, but if auth-service is switched to a worktree and api-gateway depends on it, the cascade doesn't switch api-gateway too. For tightly coupled services that should be tested from the same branch, a "cascade switch" would reduce manual steps.

Diff preview before switching. Before rebuilding from a worktree, showing a summary of what changed (files modified, services affected) would help you decide whether the switch is worth the rebuild time, especially when Claude has been working for a while and you're not sure what exactly changed.

Branch status indicators. Showing whether a worktree's branch is ahead/behind main, or has uncommitted changes, would help you decide which worktree to test — a branch that's 30 commits ahead is a different risk profile than one that changed a single config file.

Multi-service worktree switch. A single action to switch all services from one compose file to the same worktree, because when Claude works on changes that span multiple services in the same repo, switching them one by one is unnecessary friction.

Install

npm install -g recomposable
Enter fullscreen mode Exit fullscreen mode

Navigate to a directory with a docker-compose.yml, create a recomposable.json pointing to your compose files, and run recomposable. The worktree feature works out of the box with any git repository that has multiple worktrees.

GitHub | npm

Top comments (0)