<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Suleyman</title>
    <description>The latest articles on DEV Community by Suleyman (@_suleyman).</description>
    <link>https://dev.to/_suleyman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3862773%2F3e3d6904-7e97-4286-ae98-672e9fc2f4e8.jpg</url>
      <title>DEV Community: Suleyman</title>
      <link>https://dev.to/_suleyman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_suleyman"/>
    <language>en</language>
    <item>
      <title>Git Worktrees: How to Run Multiple Claude Code Sessions at Once</title>
      <dc:creator>Suleyman</dc:creator>
      <pubDate>Sun, 07 Jun 2026 18:51:12 +0000</pubDate>
      <link>https://dev.to/_suleyman/git-worktrees-how-to-run-multiple-claude-code-sessions-at-once-1i81</link>
      <guid>https://dev.to/_suleyman/git-worktrees-how-to-run-multiple-claude-code-sessions-at-once-1i81</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Git worktrees let you check out multiple branches at the same time, each in its own folder, all sharing one &lt;code&gt;.git&lt;/code&gt; directory. And with Claude Code's &lt;code&gt;--worktree&lt;/code&gt; flag, you can run multiple AI coding sessions at once without file conflicts. This guide covers everything from first setup to parallel AI workflows.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;You're working on a feature. You have uncommitted changes. A production bug comes in and needs a fix now.&lt;/p&gt;

&lt;p&gt;With standard Git, you have three bad options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git stash&lt;/code&gt; everything, switch branches, fix the bug, &lt;code&gt;git stash pop&lt;/code&gt;, get back to where you were&lt;/li&gt;
&lt;li&gt;Clone the repo a second time and manage two out-of-sync copies&lt;/li&gt;
&lt;li&gt;Make a half-finished WIP commit just so you can switch branches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git worktrees remove all three of these options by letting you work on multiple branches at the same time, each in its own folder.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Git Worktrees?
&lt;/h2&gt;

&lt;p&gt;A worktree is a folder with its own branch checked out. It shares the same &lt;code&gt;.git&lt;/code&gt; history as your main project, but has its own working files.&lt;/p&gt;

&lt;p&gt;A normal clone gives you one folder, one branch at a time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/my-project/
  .git/         ← history lives here
  src/
  package.json  ← whatever branch you have checked out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With worktrees, you get multiple folders, each on its own branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/my-project/
  .git/              ← one shared history
  src/
  package.json       ← main branch

~/my-project-auth/
  src/
  package.json       ← feature/auth branch

~/my-project-hotfix/
  src/
  package.json       ← hotfix/payment-crash branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can edit files in all three folders at the same time. Changes in one folder don't touch the others. And since they share one &lt;code&gt;.git&lt;/code&gt;, a &lt;code&gt;git fetch&lt;/code&gt; in any folder makes new remote branches visible everywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's shared vs. what's separate
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shared across all worktrees&lt;/th&gt;
&lt;th&gt;Separate per worktree&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Commit history&lt;/td&gt;
&lt;td&gt;Checked-out branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote refs (after a fetch)&lt;/td&gt;
&lt;td&gt;Staged changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hooks&lt;/td&gt;
&lt;td&gt;Unstaged changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local Git config&lt;/td&gt;
&lt;td&gt;Working directory files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local branches&lt;/td&gt;
&lt;td&gt;Shell &lt;code&gt;$PWD&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tags&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;MERGE_HEAD&lt;/code&gt;, &lt;code&gt;CHERRY_PICK_HEAD&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Worktrees vs. Multiple Clones
&lt;/h2&gt;

&lt;p&gt;Some people solve the "two branches at once" problem by cloning the repo twice. Here's why that's worse:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storage.&lt;/strong&gt; Every clone copies the full &lt;code&gt;.git&lt;/code&gt; object store. A 500 MB repo becomes 1 GB across two clones. Worktrees only add the weight of the working files — usually a few megabytes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No shared state.&lt;/strong&gt; &lt;code&gt;git fetch&lt;/code&gt; in Clone A does nothing for Clone B. A local branch you create in Clone A doesn't exist in Clone B until you push it. You're managing two separate databases by hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks only exist in one place.&lt;/strong&gt; Git hooks (pre-commit linting, push guards, etc.) live in &lt;code&gt;.git/hooks&lt;/code&gt;. Clone B starts with nothing. With worktrees, all hooks apply everywhere because there's one &lt;code&gt;.git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git protects you.&lt;/strong&gt; Git won't let you check out the same branch in two worktrees at once. With two clones, nothing stops both from modifying the same branch simultaneously. You won't notice until you push.&lt;/p&gt;




&lt;h2&gt;
  
  
  Basic Setup: Your First Worktree
&lt;/h2&gt;

&lt;p&gt;Start from a normal clone. These commands work from there.&lt;/p&gt;

&lt;h3&gt;
  
  
  New worktree, new branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Creates ../feature-auth directory on a new branch named feature/auth&lt;/span&gt;
git worktree add ../feature-auth &lt;span class="nt"&gt;-b&lt;/span&gt; feature/auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The path and the branch name are independent. Use &lt;code&gt;-b&lt;/code&gt; to name them separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  New worktree, auto-named branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Branch name comes from the last part of the path: "feature-auth"&lt;/span&gt;
git worktree add ../feature-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Git names the branch after the last path segment. Fine for quick tasks. Use &lt;code&gt;-b&lt;/code&gt; when the branch name matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worktree from an existing branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check out a branch that already exists&lt;/span&gt;
git worktree add ../bugfix-session bugfix/payment-crash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Worktree from a remote branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a local branch that tracks the remote one&lt;/span&gt;
git worktree add &lt;span class="nt"&gt;-b&lt;/span&gt; feature/dark-mode ../dark-mode origin/feature/dark-mode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this to review a colleague's branch without touching your own work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Then work normally
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../feature-auth
npm &lt;span class="nb"&gt;install&lt;/span&gt;       &lt;span class="c"&gt;# each worktree needs its own node_modules&lt;/span&gt;
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each worktree is a fresh checkout. Dependencies, virtual environments, and build output are not shared between worktrees. Install them in each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  List your worktrees
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/you/my-project        abc1234 [main]
/home/you/feature-auth      def5678 [feature/auth]
/home/you/bugfix-session    ghi9012 [bugfix/payment-crash]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Remove a worktree
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree remove ../feature-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removes the folder and the Git bookkeeping. The branch stays unless you delete it with &lt;code&gt;git branch -d feature/auth&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bare Clone Setup
&lt;/h2&gt;

&lt;p&gt;The basic setup works, but the folder layout is awkward. Your main checkout sits alongside its own worktrees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/my-project/    ← main branch (also has working files)
~/feature-auth/  ← worktree
~/bugfix/        ← worktree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main branch is in a special position even though it shouldn't be. Worktrees should all be equal.&lt;/p&gt;

&lt;p&gt;The bare clone setup fixes this. Instead of a normal clone, you clone only the history — no working files — and create every branch as a worktree, including &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to set it up
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Create a clean project folder&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/Projects/my-project
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Projects/my-project

&lt;span class="c"&gt;# 2. Clone history only, no working files&lt;/span&gt;
git clone &lt;span class="nt"&gt;--bare&lt;/span&gt; git@github.com:user/repo.git .bare

&lt;span class="c"&gt;# 3. Tell Git where the history is&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"gitdir: ./.bare"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .git

&lt;span class="c"&gt;# 4. Fix remote tracking — required, see explanation below&lt;/span&gt;
git config remote.origin.fetch &lt;span class="s2"&gt;"+refs/heads/*:refs/remotes/origin/*"&lt;/span&gt;

&lt;span class="c"&gt;# 5. Fetch all remote branches&lt;/span&gt;
git fetch &lt;span class="nt"&gt;--all&lt;/span&gt;

&lt;span class="c"&gt;# 6. Create your first worktree&lt;/span&gt;
git worktree add main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your folder now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/Projects/my-project/
  .bare/    ← git history
  .git      ← one-line file pointing to .bare
  main/     ← worktree for main branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add more as needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add feature/auth
git worktree add hotfix/payment-crash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/Projects/my-project/
  .bare/
  .git
  main/
  feature/
    auth/
  hotfix/
    payment-crash/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every branch is a folder. When work is done and merged, remove the folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "blind clone" problem
&lt;/h3&gt;

&lt;p&gt;After a bare clone, run &lt;code&gt;git fetch&lt;/code&gt; and you might see only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* branch            HEAD       -&amp;gt; FETCH_HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means Git only knows about the default branch. All other remote branches are invisible.&lt;/p&gt;

&lt;p&gt;This happens because bare clones are designed as server mirrors, not dev environments. They don't set up remote tracking by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config remote.origin.fetch &lt;span class="s2"&gt;"+refs/heads/*:refs/remotes/origin/*"&lt;/span&gt;
git fetch &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line tells Git to map every remote branch to a local tracking reference. After that, &lt;code&gt;git fetch --all&lt;/code&gt; shows everything. Run these two lines every time you do a bare clone.&lt;/p&gt;

&lt;p&gt;If you skip this step, &lt;code&gt;git worktree add&lt;/code&gt; will silently create a new empty branch instead of checking out the remote branch you wanted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation script
&lt;/h3&gt;

&lt;p&gt;Save this as &lt;code&gt;wtree&lt;/code&gt; in your &lt;code&gt;~/.local/bin/&lt;/code&gt; and run &lt;code&gt;chmod +x wtree&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Usage: wtree &amp;lt;git-url&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;# Run this in an empty folder.&lt;/span&gt;

&lt;span class="nv"&gt;REPO_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="nv"&gt;SCRIPT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;repo-url&amp;gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SCRIPT_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: folder is not empty."&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;git clone &lt;span class="nt"&gt;--bare&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; .bare
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"gitdir: ./.bare"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .git
git config remote.origin.fetch &lt;span class="s2"&gt;"+refs/heads/*:refs/remotes/origin/*"&lt;/span&gt;
git fetch &lt;span class="nt"&gt;--all&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Done. Run: git worktree add main"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Command Reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;git worktree add&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# New branch, explicit name&lt;/span&gt;
git worktree add &amp;lt;path&amp;gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;branch&amp;gt;

&lt;span class="c"&gt;# New branch, name comes from path&lt;/span&gt;
git worktree add &amp;lt;path&amp;gt;

&lt;span class="c"&gt;# Existing local branch&lt;/span&gt;
git worktree add &amp;lt;path&amp;gt; &amp;lt;existing-branch&amp;gt;

&lt;span class="c"&gt;# From a remote branch&lt;/span&gt;
git worktree add &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;local-name&amp;gt; &amp;lt;path&amp;gt; &amp;lt;remote&amp;gt;/&amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;git worktree list&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree list

&lt;span class="c"&gt;# Machine-readable output&lt;/span&gt;
git worktree list &lt;span class="nt"&gt;--porcelain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;git worktree remove&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Remove a worktree (fails if there are uncommitted changes)&lt;/span&gt;
git worktree remove &amp;lt;path&amp;gt;

&lt;span class="c"&gt;# Force removal, discards uncommitted changes&lt;/span&gt;
git worktree remove &lt;span class="nt"&gt;--force&lt;/span&gt; &amp;lt;path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;git worktree prune&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you delete a worktree folder with &lt;code&gt;rm -rf&lt;/code&gt; instead of &lt;code&gt;git worktree remove&lt;/code&gt;, Git keeps stale records pointing to the now-missing folder. &lt;code&gt;prune&lt;/code&gt; cleans those up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Remove stale records&lt;/span&gt;
git worktree prune

&lt;span class="c"&gt;# Preview what would be removed&lt;/span&gt;
git worktree prune &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;git worktree lock&lt;/code&gt; / &lt;code&gt;unlock&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Prevent &lt;code&gt;prune&lt;/code&gt; from removing a worktree — useful for worktrees on external drives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree lock &amp;lt;path&amp;gt; &lt;span class="nt"&gt;--reason&lt;/span&gt; &lt;span class="s2"&gt;"On external drive"&lt;/span&gt;
git worktree unlock &amp;lt;path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;git worktree move&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Move a worktree to a new path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree move ../feature-auth ../workspaces/feature-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;git worktree repair&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you moved the &lt;code&gt;.git&lt;/code&gt; directory or the worktree folder manually, Git loses track of it. Run this from inside the worktree to re-link it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree repair
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Workflows
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hotfix while in the middle of a feature
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# You're in ~/project/feature/redesign with uncommitted work.&lt;/span&gt;
&lt;span class="c"&gt;# A bug needs fixing now. Don't stash, don't stop.&lt;/span&gt;

&lt;span class="c"&gt;# From the project root, add a worktree for the fix&lt;/span&gt;
git worktree add hotfix/payment-crash

&lt;span class="c"&gt;# Open a second terminal&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/project/hotfix/payment-crash
&lt;span class="c"&gt;# Fix the bug&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix: null check on payment processor callback"&lt;/span&gt;
git push origin hotfix/payment-crash

&lt;span class="c"&gt;# Your first terminal still has the redesign exactly where you left it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compare two implementations side by side
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add approach-a &lt;span class="nt"&gt;-b&lt;/span&gt; experiment/approach-a
git worktree add approach-b &lt;span class="nt"&gt;-b&lt;/span&gt; experiment/approach-b

&lt;span class="c"&gt;# Two terminals, two dev servers&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;approach-a &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run dev &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 3001
&lt;span class="nb"&gt;cd &lt;/span&gt;approach-b &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run dev &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 3002

&lt;span class="c"&gt;# Open both in the browser and compare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Review a PR without losing your place
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin pull/1234/head:pr-1234
git worktree add ../pr-1234 pr-1234

&lt;span class="nb"&gt;cd&lt;/span&gt; ../pr-1234
&lt;span class="c"&gt;# Review, run tests, check behavior&lt;/span&gt;

&lt;span class="c"&gt;# When done&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
git worktree remove pr-1234
git branch &lt;span class="nt"&gt;-d&lt;/span&gt; pr-1234
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Long-running parallel features
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add feature/payments &lt;span class="nt"&gt;-b&lt;/span&gt; feature/payments
git worktree add feature/notifications &lt;span class="nt"&gt;-b&lt;/span&gt; feature/notifications

&lt;span class="c"&gt;# Work on payments in one terminal, notifications in another.&lt;/span&gt;
&lt;span class="c"&gt;# git fetch in either one updates both.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Shell Aliases and Shortcuts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Git aliases
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.wta &lt;span class="s1"&gt;'!f() { git worktree add -b "$1" "../$1"; }; f'&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.wtr &lt;span class="s1"&gt;'!f() { git worktree remove "../$1"; }; f'&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.wtl &lt;span class="s1"&gt;'worktree list'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git wta feature-auth    &lt;span class="c"&gt;# creates ../feature-auth on branch feature-auth&lt;/span&gt;
git wtr feature-auth    &lt;span class="c"&gt;# removes it&lt;/span&gt;
git wtl                 &lt;span class="c"&gt;# lists all worktrees&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PR checkout function
&lt;/h3&gt;

&lt;p&gt;Add to your &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt;. Requires the &lt;a href="https://cli.github.com/" rel="noopener noreferrer"&gt;GitHub CLI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Usage: cpr &amp;lt;PR_NUMBER&amp;gt;&lt;/span&gt;
cpr&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local pr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;remote&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;origin&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;branch
  &lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gh &lt;span class="nb"&gt;pr &lt;/span&gt;view &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt; headRefName &lt;span class="nt"&gt;-q&lt;/span&gt; .headRefName&lt;span class="si"&gt;)&lt;/span&gt;
  git fetch &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  git worktree add &lt;span class="s2"&gt;"../&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"../&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ready: PR #&lt;/span&gt;&lt;span class="nv"&gt;$pr&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;cpr 1234&lt;/code&gt; and you're in a folder with that PR checked out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fuzzy worktree switcher
&lt;/h3&gt;

&lt;p&gt;Requires &lt;a href="https://github.com/junegunn/fzf" rel="noopener noreferrer"&gt;&lt;code&gt;fzf&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wts&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;selected
  &lt;span class="nv"&gt;selected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git worktree list | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt; | fzf &lt;span class="nt"&gt;--prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Switch to worktree: "&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$selected&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$selected&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;wts&lt;/code&gt;, search by name, press Enter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Editor Tooling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  VS Code, Cursor, Windsurf
&lt;/h3&gt;

&lt;p&gt;Install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=PhilStainer.git-worktree" rel="noopener noreferrer"&gt;Git Worktree extension&lt;/a&gt; by PhilStainer. It adds worktree commands to the Command Palette:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List and jump between worktrees&lt;/li&gt;
&lt;li&gt;Add and remove worktrees from the GUI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each worktree opens as a separate VS Code window since each is a different folder on disk. Treat each one as its own project.&lt;/p&gt;

&lt;p&gt;Pairs well with the &lt;a href="https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager" rel="noopener noreferrer"&gt;Project Manager extension&lt;/a&gt; if you switch between many worktrees often.&lt;/p&gt;

&lt;h3&gt;
  
  
  Neovim / Vim
&lt;/h3&gt;

&lt;p&gt;Session managers like &lt;a href="https://github.com/tpope/vim-obsession" rel="noopener noreferrer"&gt;vim-obsession&lt;/a&gt; or &lt;a href="https://github.com/folke/persistence.nvim" rel="noopener noreferrer"&gt;persistence.nvim&lt;/a&gt; save a session per directory automatically, so each worktree gets its own saved state.&lt;/p&gt;

&lt;h3&gt;
  
  
  JetBrains IDEs
&lt;/h3&gt;

&lt;p&gt;Open each worktree as a separate project window. The IDE detects the shared &lt;code&gt;.git&lt;/code&gt; and shows branch info correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Claude Code + Worktrees
&lt;/h2&gt;

&lt;p&gt;Without worktrees, two Claude Code sessions in the same directory will overwrite each other's files. The second session has no idea what the first wrote. You get silent conflicts.&lt;/p&gt;

&lt;p&gt;Worktrees give each session its own directory and branch. They can run at the same time without touching each other's work.&lt;/p&gt;

&lt;p&gt;Claude Code has this built in with the &lt;code&gt;--worktree&lt;/code&gt; flag.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start a session in a worktree
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--worktree&lt;/span&gt; feature-auth
&lt;span class="c"&gt;# short form:&lt;/span&gt;
claude &lt;span class="nt"&gt;-w&lt;/span&gt; bugfix-payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude creates &lt;code&gt;.claude/worktrees/feature-auth/&lt;/code&gt;, checks out a new branch named &lt;code&gt;worktree-feature-auth&lt;/code&gt;, and starts the session there.&lt;/p&gt;

&lt;p&gt;Open another terminal and run a second session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;-w&lt;/span&gt; bugfix-payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both run at the same time. Neither can see the other's files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First-time setup:&lt;/strong&gt; Before using &lt;code&gt;--worktree&lt;/code&gt; in a repo, run &lt;code&gt;claude&lt;/code&gt; once in that directory to accept the workspace trust prompt. After that, the flag works without extra steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let Claude pick a name
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--worktree&lt;/span&gt;
&lt;span class="c"&gt;# Creates something like: .claude/worktrees/bright-running-fox/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check out a pull request
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--worktree&lt;/span&gt; &lt;span class="s2"&gt;"#1234"&lt;/span&gt;
&lt;span class="c"&gt;# Creates .claude/worktrees/pr-1234/ from that PR's branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude fetches the branch and starts the session in it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy &lt;code&gt;.env&lt;/code&gt; files into every worktree
&lt;/h3&gt;

&lt;p&gt;Worktrees are fresh checkouts. Files like &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;.env.local&lt;/code&gt; won't be there unless you copy them.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.worktreeinclude&lt;/code&gt; file in the project root. Same syntax as &lt;code&gt;.gitignore&lt;/code&gt;. Only files that match AND are already gitignored will be copied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# .worktreeinclude
&lt;/span&gt;.&lt;span class="n"&gt;env&lt;/span&gt;
.&lt;span class="n"&gt;env&lt;/span&gt;.&lt;span class="n"&gt;local&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;/&lt;span class="n"&gt;secrets&lt;/span&gt;.&lt;span class="n"&gt;json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This applies to every worktree Claude creates — via &lt;code&gt;--worktree&lt;/code&gt;, via subagents, or via the desktop app.&lt;/p&gt;

&lt;p&gt;Also add this to &lt;code&gt;.gitignore&lt;/code&gt; so worktree contents don't show up as untracked files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.claude/worktrees/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Isolate subagents
&lt;/h3&gt;

&lt;p&gt;When Claude delegates work to subagents, multiple subagents can write to the same files at once — same conflict problem. Tell Claude to isolate them:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Use worktrees for your agents."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or set it permanently in a custom subagent's frontmatter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend-agent&lt;/span&gt;
&lt;span class="na"&gt;isolation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worktree&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each subagent gets its own worktree. When the subagent finishes with no changes, the worktree is removed automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Base branch: remote vs. local HEAD
&lt;/h3&gt;

&lt;p&gt;By default, new worktrees branch from &lt;code&gt;origin/HEAD&lt;/code&gt; — the latest remote state. To branch from your current local &lt;code&gt;HEAD&lt;/code&gt; instead (including unpushed commits), add this to your Claude Code settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"worktree"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseRef"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"head"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;"head"&lt;/code&gt; when subagents need to work on code you haven't pushed yet. Use the default when you want each session to start from a clean remote state.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens when a session ends
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Session state on exit&lt;/th&gt;
&lt;th&gt;What Claude does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No commits, no changes&lt;/td&gt;
&lt;td&gt;Removes the worktree and branch automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Has commits or uncommitted changes&lt;/td&gt;
&lt;td&gt;Asks: keep or remove?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-interactive mode (&lt;code&gt;-p&lt;/code&gt; flag)&lt;/td&gt;
&lt;td&gt;No cleanup — remove manually&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To clean up manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree list
git worktree remove .claude/worktrees/feature-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Desktop app
&lt;/h3&gt;

&lt;p&gt;The Claude Code desktop app creates a worktree for every new parallel session automatically. No flags needed. &lt;code&gt;.worktreeinclude&lt;/code&gt; still applies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three sessions at once: a full example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .gitignore&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".claude/worktrees/"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore

&lt;span class="c"&gt;# .worktreeinclude&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".env"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .worktreeinclude

&lt;span class="c"&gt;# Three terminals&lt;/span&gt;
claude &lt;span class="nt"&gt;-w&lt;/span&gt; add-oauth-login
claude &lt;span class="nt"&gt;-w&lt;/span&gt; fix-rate-limiter
claude &lt;span class="nt"&gt;-w&lt;/span&gt; migrate-to-drizzle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When each finishes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Review the work&lt;/span&gt;
git diff main..worktree-add-oauth-login
git diff main..worktree-fix-rate-limiter
git diff main..worktree-migrate-to-drizzle

&lt;span class="c"&gt;# Merge what's good&lt;/span&gt;
git merge worktree-fix-rate-limiter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Deleting a folder with &lt;code&gt;rm -rf&lt;/code&gt; instead of &lt;code&gt;git worktree remove&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Git keeps records pointing to the deleted folder. The next time you try to add a worktree at the same path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fatal: 'feature-auth' is already checked out at '...'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree prune
git worktree add &amp;lt;path&amp;gt; &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  You can't check out the same branch in two worktrees
&lt;/h3&gt;

&lt;p&gt;Git blocks this. If you need two sessions on the same branch, create a new branch from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add ../review-copy &lt;span class="nt"&gt;-b&lt;/span&gt; review/feature-auth feature/auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dependencies aren't shared
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;node_modules&lt;/code&gt;, Python virtual environments, compiled binaries — each worktree needs its own. After creating a worktree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../new-worktree
npm &lt;span class="nb"&gt;install&lt;/span&gt;   &lt;span class="c"&gt;# or pip install, cargo build, etc.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bare clone without the fetch fix
&lt;/h3&gt;

&lt;p&gt;After &lt;code&gt;git clone --bare&lt;/code&gt;, always run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config remote.origin.fetch &lt;span class="s2"&gt;"+refs/heads/*:refs/remotes/origin/*"&lt;/span&gt;
git fetch &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skip this and you can only see the default branch. Everything else on the remote is invisible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running many sessions in parallel is resource-heavy
&lt;/h3&gt;

&lt;p&gt;Multiple Claude sessions each running tests, compilation, and a dev server adds up. Four parallel sessions runs fine on an M-series Mac with 16 GB RAM. Adjust based on your hardware.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;claude --worktree&lt;/code&gt; fails with a workspace trust error
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;claude&lt;/code&gt; once in the project folder to accept the trust prompt. Then &lt;code&gt;--worktree&lt;/code&gt; works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude      &lt;span class="c"&gt;# accept the prompt, then Ctrl+C&lt;/span&gt;
claude &lt;span class="nt"&gt;-w&lt;/span&gt; my-task   &lt;span class="c"&gt;# now works&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Cheat Sheet
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Git commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create worktree (new branch)&lt;/span&gt;
git worktree add &amp;lt;path&amp;gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;branch&amp;gt;

&lt;span class="c"&gt;# Create worktree (existing branch)&lt;/span&gt;
git worktree add &amp;lt;path&amp;gt; &amp;lt;existing-branch&amp;gt;

&lt;span class="c"&gt;# Create worktree (from remote branch)&lt;/span&gt;
git worktree add &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;name&amp;gt; &amp;lt;path&amp;gt; &amp;lt;remote&amp;gt;/&amp;lt;branch&amp;gt;

&lt;span class="c"&gt;# List all worktrees&lt;/span&gt;
git worktree list

&lt;span class="c"&gt;# Remove a worktree&lt;/span&gt;
git worktree remove &amp;lt;path&amp;gt;

&lt;span class="c"&gt;# Clean up stale worktree records&lt;/span&gt;
git worktree prune

&lt;span class="c"&gt;# Lock a worktree (protect from prune)&lt;/span&gt;
git worktree lock &amp;lt;path&amp;gt;

&lt;span class="c"&gt;# Move a worktree&lt;/span&gt;
git worktree move &amp;lt;old-path&amp;gt; &amp;lt;new-path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Git aliases
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.wta &lt;span class="s1"&gt;'!f() { git worktree add -b "$1" "../$1"; }; f'&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.wtr &lt;span class="s1"&gt;'!f() { git worktree remove "../$1"; }; f'&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.wtl &lt;span class="s1"&gt;'worktree list'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bare clone setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/Projects/my-project &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~/Projects/my-project
git clone &lt;span class="nt"&gt;--bare&lt;/span&gt; &amp;lt;repo-url&amp;gt; .bare
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"gitdir: ./.bare"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .git
git config remote.origin.fetch &lt;span class="s2"&gt;"+refs/heads/*:refs/remotes/origin/*"&lt;/span&gt;
git fetch &lt;span class="nt"&gt;--all&lt;/span&gt;
git worktree add main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Named worktree&lt;/span&gt;
claude &lt;span class="nt"&gt;--worktree&lt;/span&gt; &amp;lt;name&amp;gt;
claude &lt;span class="nt"&gt;-w&lt;/span&gt; &amp;lt;name&amp;gt;

&lt;span class="c"&gt;# Auto-named&lt;/span&gt;
claude &lt;span class="nt"&gt;--worktree&lt;/span&gt;

&lt;span class="c"&gt;# From a pull request&lt;/span&gt;
claude &lt;span class="nt"&gt;--worktree&lt;/span&gt; &lt;span class="s2"&gt;"#&amp;lt;pr-number&amp;gt;"&lt;/span&gt;

&lt;span class="c"&gt;# settings.json — branch from local HEAD&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"worktree"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"baseRef"&lt;/span&gt;: &lt;span class="s2"&gt;"head"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Files to create in your project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .gitignore&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".claude/worktrees/"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore

&lt;span class="c"&gt;# .worktreeinclude&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".env"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .worktreeinclude
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".env.local"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .worktreeinclude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Worktrees change one thing: instead of having one branch checked out at a time, every branch is a folder. Switching context means opening a different terminal, not stashing and hoping you remember what you were doing.&lt;/p&gt;

&lt;p&gt;The bare clone setup takes five minutes to learn and gives you a cleaner structure for repos where you work across many branches regularly.&lt;/p&gt;

&lt;p&gt;If you use Claude Code, the &lt;code&gt;--worktree&lt;/code&gt; flag is the practical way to run multiple sessions without them stepping on each other. Set up &lt;code&gt;.worktreeinclude&lt;/code&gt; once, add &lt;code&gt;.claude/worktrees/&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;, and you're done.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>git</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
