Skip to main content

Command Palette

Search for a command to run...

How I Use Git Worktrees to Keep Multiple AI Sessions Alive Without Losing My Flow

Published
6 min read
How I Use Git Worktrees to Keep Multiple AI Sessions Alive Without Losing My Flow

1. Why I Started Using Worktrees

At the beginning, I was juggling several copies of the same project in different folders. Sometimes I did it even before using AI — mostly to avoid long Xcode rebuilds or to keep a clean environment while experimenting with a feature. It wasn’t elegant, but it worked, and I didn’t think too much about it.

Once I started using AI more seriously in my development flow, this habit suddenly became limiting. I naturally work on several pieces of code throughout the day — planning a feature in the morning, testing or refining another branch around midday, and reviewing or polishing something else in the afternoon. That rhythm only works if each piece of work can stay alive in its own environment, with its own build state and its own AI-assisted context.

The solution didn’t come from Git docs or some deep research — it came from a simple ChatGPT question. I asked how to avoid cloning the same repo so many times, and the answer pointed straight to worktrees. A feature designed years ago for this exact use case, sitting there quietly while I kept doing things the slow way.

From the outside, worktrees sounded like advanced Git magic. In reality, they’re a straightforward, one-time setup that gives you parallel working directories tied to the same .git repository. One for your stable main branch, and then as many isolated feature worktrees as you need — each with its own branch, its own build products, and its own AI session that keeps context.

Worktrees didn’t just simplify my setup — they made the whole day flow more naturally.

2. The Core Idea of Git Worktrees

At their core, worktrees solve a very simple problem: working on multiple branches at the same time without constantly switching, stashing, or cloning your entire repository. In real engineering workflows, context switching is expensive — not just mentally, but technically. Xcode rebuilds everything, the AI loses track of the files it was reasoning about, and you end up hesitating to touch anything because you’re afraid of breaking the state you’re currently debugging.

There is one catch, though: Xcode doesn’t handle multiple parallel views of the same codebase very well. You can open completely different projects side-by-side, but you can’t open two worktrees of the same repo at the same time — Xcode will start producing strange, inconsistent build errors, missing symbols, or stale DerivedData issues. And the same limitation applies to dependencies: you also can’t open a package dependency in Xcode while simultaneously having the consuming app open. Xcode mixes build products, confuses module references, and ends up in a broken state that’s extremely hard to debug. The practical rule is simple: Close Xcode, open the worktree instance you ned to debug/run.

In practice, worktrees do one thing incredibly well: they give you parallel worlds that stay clean, isolated, and always in sync with how you actually work.

3. How I Structure My Worktree Setup

My setup is built around a single base repository with a few related worktrees that live right next to it in the same folder. They all share the same .git data, but each one has its own working directory, its own branch, and its own AI session.

git/
  <repo-name>
  <repo-name>-two
  <repo-name>-three

I also tie each worktree to a tmux session with the same naming (I’ll go deeper into that in the next article). That gives me a very simple mapping in my head.

To keep everything visible and predictable, I split my iTerm window into four panes. Three of them are permanently attached to their own tmux sessions, each mapped to one of the worktrees. This gives me three parallel AI conversations running in dedicated environments — each pane showing logs, diffs, test output, or whatever Claude and I are working on in that specific universe. The fourth pane is my “navigation pane,” where I can freely jump between folders whenever I need to test the product of a worktree, run a quick command, or inspect something without disturbing the AI sessions. This layout gives me a reliable mental map: three isolated development lanes and one flexible pane that I can repurpose as needed throughout the day, without ever losing context.

4. Creating and Managing Worktrees (Focused, Practical Snippets)

Worktrees look more complex than they are. In practice, you can manage your entire setup with just a handful of short commands.

Add a new worktree

Create a new worktree attached to a branch (if the branch doesn’t exist, Git will create it):

git worktree add ../<repo-name>-two feature/my-feature

List all active worktrees

Useful to remind yourself what’s attached to the repo:

git worktree list

Remove or detach a worktree safely

Depending on your preference, you might want to have more or less worktrees in parallel.

git worktree remove <repo-name>-two

Fork (Git client) supports native worktree switching

I also prefer using Fork, the Git client, because it makes navigating changes across worktrees effortless. Fork understands worktrees natively, so switching between them — or reviewing diffs, commits, and branches — feels clean and predictable. It keeps everything organized, has a clean UI and and it’s especially helpful when juggling several active worktrees in a large project.

In theory, the “pure Git” approach is to delete a worktree as soon as you finish working on its feature. But in practice, that would mean recreating the worktree every single morning, which becomes friction when you rely on a stable setup tied to tmux sessions and fixed terminal panes. Fork also doesn’t automate this lifecycle, so spinning worktrees up and down constantly isn’t worth the overhead. Instead, when a feature is merged, I create a lightweight placeholder branch so the worktree can stay alive and attached. Git doesn’t allow two worktrees to check out the same branch at once, so the placeholder keeps everything unblocked and lets me preserve my layout. It’s not ideal, and realistically an easy shell automation could solve it, but for now this workaround keeps the workflow predictable. I’m still experimenting with this setup, and I prefer having a working solution before committing too much effort to something I might change my mind about tomorrow.

5. Closing Summary

To wrap things up, here are the key ideas that make this setup work:

  • Worktrees keep AI-assisted development stable by giving each feature its own isolated universe.

  • The core mental model is simple: one worktree → one tmux session → one branch → one AI thread.

  • The command set is minimal — add, remove, list — just enough to spin up or tear down environments without ceremony.

  • This setup aligns naturally with how I work during the day, switching between features without losing context.

  • Fork makes navigating changes effortless, even with several active worktrees.

In the next articles, I’ll go deeper into:

  • How I use tmux + Terminus/Blink to keep these sessions alive on the move.

  • How to run multiple concurrent AI-powered development sessions without losing state or rebuilding anything.

This workflow is still evolving, but so far it’s been one of the simplest ways to keep AI, Git, and Xcode cooperating without getting in each other’s way.