RSS Amplifier

Andreas Fertsch-Röver · Mar 6, 2026

My LLM Git Workflow: Parallel Development with Worktrees and Claude

0
Sign in to vote or save

Andreas Fertsch-Röver · Andreas Fertsch-Röver

Skip to content

Since I started using Claude Code for day-to-day development, my git workflow has changed significantly. The biggest shift: multiple branches checked out simultaneously, each in its own directory, with no interference between them. Here is how I do it.

The Problem with One Working Copy

The traditional workflow has everyone working in a single checkout. When you need to jump between tickets you switch branches — and that causes interference. Your editor reindexes, the build tool sees changed files, and the IDE plugin gets confused about which version of the code it is looking at.

With worktrees each branch lives in its own directory. There is no switching — you open a different window. Branches never interfere with each other.

Worktrees to the Rescue

Git worktrees let you check out multiple branches simultaneously into separate directories. Each directory is a fully independent working copy of the repository, sharing only the .git folder.

# Branch already exists (created via Jira, GitHub, or your IDE)
# Add a worktree for it in a sibling directory
git fetch origin
git worktree add ../my-project-TICKET-123 feature/TICKET-123-my-feature

Now I have two directories side by side:

projects/
├── my-project/                  # main branch, always clean
└── my-project-TICKET-123/       # feature branch, worktree

The Full Workflow

1. Ticket → Branch → Worktree

When a new ticket lands I create the branch first — from Jira, GitHub, or my IDE — then add a worktree for it:

git worktree add ../my-project-TICKET-123 feature/TICKET-123-description

2. Open VS Code with Claude Code in the Worktree

Open the worktree in VS Code, run an initial compile to generate sources and populate target/, then start Claude Code from the terminal:

code ../my-project-TICKET-123
./mvnw compile
claude

Claude Code sees only this worktree — one ticket, no noise from other branches.

3. Work in Small, Committed Steps

After each meaningful change I commit with a descriptive message. Claude Code helps here too — I use a /commit-msg skill to generate a good message from the staged diff.

git add .
git commit -m "feat: add validation for TICKET-123 input fields"

Small commits keep the history readable and make code review easier.

4. Push and Open a PR

When the ticket is done:

git push -u origin feature/TICKET-123-description

Then open the PR manually in the browser.

5. Cleanup After Merge

Once the PR is merged:

git worktree remove ../my-project-TICKET-123
git branch -d feature/TICKET-123-description

Two commands remove the worktree directory and delete the branch.

The Benefits

Parallel Work Without Switching

The biggest win: I can have multiple tickets in flight simultaneously. Each has its own directory, its own editor window, its own Claude session. Switching between them is switching windows — no stashing, no confused IDE plugins.

Java Tooling Stays Happy

Java IDEs and build tools are sensitive to branch switches. Changing branches under a running Quarkus dev server causes it to recompile. Changing to a branch with a different code version can confuse IDE plugins.

With worktrees none of this happens. The main project directory never changes branch. Each feature lives in its own directory with its own compile cache.

Note

Each new worktree needs its own initial build. Run ./mvnw compile once in the new directory and you are set.

Claude Has Full Ticket Context

Because each worktree has its own Claude Code session, the AI builds up context for exactly one ticket. It knows what files it changed, what the goal is, and what is left to do. There is no confusion from unrelated changes on other branches.

Git Aliases

To reduce the typing I use a few aliases in .gitconfig:

[alias]
    wt  = worktree
    wtl = worktree list
    wtr = worktree remove
    wta = "!f() { git fetch && git worktree add \"../$1\" \"$1\"; }; f"
    wtd = "!f() { git worktree remove \"../$1\" && git branch -d \"$1\"; }; f"

wta creates the worktree, wtd tears it down — both take the branch name as argument.

wta fetches, then creates the worktree in a sibling directory named after the branch:

Summary

ticket arrives
  → create branch (Jira / GitHub / IDE)
  → git wta feature/TICKET-XXX
  → code ../feature/TICKET-XXX  (then claude in VS Code terminal)
    → work, commit, work, commit
  → git push && open PR in browser
  → PR merged
  → git wtd feature/TICKET-XXX

Read the original on fertsch-roever.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.