<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Workflow on Londopy</title><link>https://londopy.github.io/blog/tags/workflow/</link><description>Recent content in Workflow on Londopy</description><image><title>Londopy</title><url>https://londopy.github.io/blog/og-image.png</url><link>https://londopy.github.io/blog/og-image.png</link></image><generator>Hugo</generator><language>en-us</language><copyright>2026 Londopy · Posts CC BY 4.0 · Code MIT</copyright><lastBuildDate>Thu, 24 Sep 2026 01:52:31 -0700</lastBuildDate><atom:link href="https://londopy.github.io/blog/tags/workflow/index.xml" rel="self" type="application/rss+xml"/><item><title>git worktree: Stop Stashing, Start Branching in Parallel</title><link>https://londopy.github.io/blog/posts/git-worktree/</link><pubDate>Thu, 01 Oct 2026 09:00:00 -0700</pubDate><guid>https://londopy.github.io/blog/posts/git-worktree/</guid><description>Check out multiple branches at the same time, in separate folders, from one repo. No stash, no second clone, no lost work.</description><content:encoded><![CDATA[<p>You&rsquo;re halfway through a feature. Files are open, tests are half-written, nothing compiles. Then someone says: &ldquo;Production is broken, can you look?&rdquo;</p>
<p>Most people do one of these:</p>
<ul>
<li><code>git stash</code>, switch branches, fix, switch back, <code>git stash pop</code>, pray.</li>
<li>Commit a &ldquo;WIP&rdquo; mess they&rsquo;ll have to clean up later.</li>
<li>Clone the whole repo again into another folder.</li>
</ul>
<p>There&rsquo;s a better option that has been in Git since 2015: <strong>worktrees</strong>.</p>
<h2 id="what-a-worktree-is">What a worktree is</h2>
<p>A normal repo has one working directory: the folder where your files live. A worktree is an <em>extra</em> working directory attached to the same repo. Each one can have a different branch checked out, and they all share the same history, objects, and remotes.</p>
<p>It&rsquo;s like a second clone, except:</p>
<ul>
<li>It&rsquo;s instant. Nothing is downloaded or copied.</li>
<li>It uses almost no extra disk space for history.</li>
<li>A commit made in one worktree is immediately visible from the others.</li>
</ul>
<h2 id="the-basics">The basics</h2>
<p>Create a worktree for an existing branch:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git worktree add ../myproject-hotfix hotfix
</span></span></code></pre></div><p>Now <code>../myproject-hotfix</code> is a full working folder with the <code>hotfix</code> branch checked out. Your original folder is untouched, half-finished feature and all.</p>
<p>Create a worktree <em>and</em> a new branch at the same time:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git worktree add -b fix-login ../myproject-fix-login main
</span></span></code></pre></div><p>That makes a new branch <code>fix-login</code> starting from <code>main</code>, checked out in a new folder.</p>
<p>See all your worktrees:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git worktree list
</span></span></code></pre></div><p>When you&rsquo;re done, remove it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git worktree remove ../myproject-hotfix
</span></span></code></pre></div><p>If you deleted a worktree folder by hand instead, clean up Git&rsquo;s records of it:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git worktree prune
</span></span></code></pre></div><h2 id="daily-uses">Daily uses</h2>
<p><strong>Emergency fixes without disruption.</strong> The scenario above. Your feature work stays exactly where you left it.</p>
<p><strong>Reviewing a pull request while you keep working.</strong> Check out the PR branch in its own worktree, run it, test it, and delete the folder when you&rsquo;re done.</p>
<p><strong>Comparing behavior side by side.</strong> Run the old version and the new version at the same time in two terminals.</p>
<p><strong>Long builds.</strong> Kick off a slow build or test suite in one worktree and keep coding in another. Your edits won&rsquo;t change files out from under the running build.</p>
<p><strong>Running AI coding agents in parallel.</strong> Give each agent its own worktree so they don&rsquo;t overwrite each other&rsquo;s changes.</p>
<h2 id="things-you-should-know">Things you should know</h2>
<p><strong>One branch, one worktree.</strong> Git won&rsquo;t let you check out the same branch in two worktrees at once, because commits in one would confuse the other. If you try, you&rsquo;ll get an error. (There&rsquo;s a <code>--force</code> flag, but you almost never want it.)</p>
<p><strong>Some things are shared, some aren&rsquo;t.</strong> Commits, branches, tags, remotes, config, and the stash are shared across all worktrees. The working files, the index (staging area), and <code>HEAD</code> are per-worktree.</p>
<p><strong>Untracked files don&rsquo;t come along.</strong> A new worktree starts clean. Your <code>.env</code>, <code>node_modules</code>, or build folders from the main worktree won&rsquo;t be there. You&rsquo;ll need to reinstall dependencies or copy config.</p>
<p><strong>Keep worktrees outside the main folder.</strong> Putting a worktree inside your main working directory makes tools, file watchers, and searches see duplicate files. A sibling folder (<code>../project-something</code>) is the usual convention.</p>
<p><strong>Lock worktrees on removable drives.</strong> If a worktree lives on a USB drive or network share that isn&rsquo;t always mounted, lock it so <code>prune</code> doesn&rsquo;t delete its records:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git worktree lock ../usb-worktree --reason <span class="s2">&#34;on external drive&#34;</span>
</span></span></code></pre></div><h2 id="a-bare-repo-trick">A bare-repo trick</h2>
<p>Some people go further: they clone a repo as <em>bare</em> (no working files at all) and do everything through worktrees:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git clone --bare git@github.com:you/project.git project/.bare
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> project
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;gitdir: ./.bare&#34;</span> &gt; .git
</span></span><span class="line"><span class="cl">git config remote.origin.fetch <span class="s2">&#34;+refs/heads/*:refs/remotes/origin/*&#34;</span>
</span></span><span class="line"><span class="cl">git fetch
</span></span><span class="line"><span class="cl">git worktree add main
</span></span><span class="line"><span class="cl">git worktree add feature-x
</span></span></code></pre></div><p>The <code>git config</code> line matters. A bare clone doesn&rsquo;t set up remote-tracking branches, so without it, <code>git fetch</code> quietly never updates them.</p>
<p>Now every branch you work on is a tidy subfolder of <code>project/</code>. It takes a little getting used to, but it makes &ldquo;which branch am I on?&rdquo; a question your file manager answers.</p>
<h2 id="closing-thought">Closing thought</h2>
<p><code>git stash</code> is fine for thirty seconds. For anything longer, stop juggling and give each branch its own folder.</p>
]]></content:encoded></item></channel></rss>