<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GitButler on recca0120 Tech Notes</title><link>https://recca0120.github.io/en/tags/gitbutler/</link><description>Recent content in GitButler on recca0120 Tech Notes</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 17 Apr 2026 17:00:00 +0800</lastBuildDate><atom:link href="https://recca0120.github.io/en/tags/gitbutler/index.xml" rel="self" type="application/rss+xml"/><item><title>GitButler: A Modern Git Client That Redesigns How You Work with Branches</title><link>https://recca0120.github.io/en/2026/04/17/gitbutler-modern-git-client/</link><pubDate>Fri, 17 Apr 2026 17:00:00 +0800</pubDate><guid>https://recca0120.github.io/en/2026/04/17/gitbutler-modern-git-client/</guid><description>&lt;img src="https://recca0120.github.io/" alt="Featured image of post GitButler: A Modern Git Client That Redesigns How You Work with Branches" /&gt;&lt;p&gt;&lt;code&gt;git rebase -i&lt;/code&gt; is the Git command I find most awkward to use. Every time I need to reorder commits, split, or squash them, I end up editing that list in vim and hoping the rebase doesn&amp;rsquo;t stop halfway through on a conflict. When it does, the repo state gets hard to reason about.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/gitbutlerapp/gitbutler" target="_blank" rel="noopener"
 &gt;GitButler&lt;/a&gt; starts from the premise that Git&amp;rsquo;s concepts are sound, but the interface can be much better. It&amp;rsquo;s a full Git client with both a GUI and a &lt;code&gt;but&lt;/code&gt; CLI, built on Tauri + Svelte + Rust. The underlying storage is still standard Git — but the hardest parts of the daily workflow have been redesigned.&lt;/p&gt;
&lt;h2 id="the-core-difference-parallel-branches"&gt;&lt;a href="#the-core-difference-parallel-branches" class="header-anchor"&gt;&lt;/a&gt;The Core Difference: Parallel Branches
&lt;/h2&gt;&lt;p&gt;The standard Git workflow is: switch to a branch, do your work, switch to another. For two simultaneous tasks you context-switch constantly, or open &lt;a class="link" href="https://recca0120.github.io/en/p/git-worktree-parallel-work/" &gt;multiple worktrees&lt;/a&gt; and manage them manually.&lt;/p&gt;
&lt;p&gt;GitButler&amp;rsquo;s &lt;strong&gt;Parallel Branches&lt;/strong&gt; let you work on multiple branches at once without switching. Drag a file&amp;rsquo;s changes to whichever branch it belongs to — that&amp;rsquo;s it.&lt;/p&gt;
&lt;p&gt;This is particularly useful for AI agent workflows, where an agent touches multiple areas simultaneously. Different tasks can be split into different branches without waiting for one to finish before starting the next.&lt;/p&gt;
&lt;h2 id="stacked-branches"&gt;&lt;a href="#stacked-branches" class="header-anchor"&gt;&lt;/a&gt;Stacked Branches
&lt;/h2&gt;&lt;p&gt;Building on top of another in-progress branch is common — open &lt;code&gt;feat/api&lt;/code&gt;, then start &lt;code&gt;feat/ui&lt;/code&gt; on top of it. The traditional approach is to rebase &lt;code&gt;feat/ui&lt;/code&gt; onto &lt;code&gt;feat/api&lt;/code&gt;, then manually rebase again every time the base branch changes.&lt;/p&gt;
&lt;p&gt;GitButler&amp;rsquo;s &lt;strong&gt;Stacked Branches&lt;/strong&gt; automate this. Edit any commit in the stack and everything above it automatically restacks.&lt;/p&gt;
&lt;h2 id="commit-management-without-rebase--i"&gt;&lt;a href="#commit-management-without-rebase--i" class="header-anchor"&gt;&lt;/a&gt;Commit Management Without &lt;code&gt;rebase -i&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;This is the most immediately noticeable improvement. Every commit operation in GitButler is drag-and-drop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Uncommit&lt;/strong&gt;: send a commit back to the working directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reword&lt;/strong&gt;: edit a commit message inline&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amend&lt;/strong&gt;: fold working-directory changes into any commit&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Move&lt;/strong&gt;: reorder commits by dragging&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Split&lt;/strong&gt;: break one commit into multiple&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Squash&lt;/strong&gt;: merge commits together&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything that used to require &lt;code&gt;git rebase -i&lt;/code&gt; is now a drag-and-drop operation.&lt;/p&gt;
&lt;h2 id="unlimited-undo"&gt;&lt;a href="#unlimited-undo" class="header-anchor"&gt;&lt;/a&gt;Unlimited Undo
&lt;/h2&gt;&lt;p&gt;Every operation is recorded in the &lt;strong&gt;Undo Timeline&lt;/strong&gt; — commits, rebases, all mutations. You can go back to any point, so there&amp;rsquo;s no fear of unrecoverable states.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;but&lt;/code&gt; CLI has matching commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;but operations-log &lt;span class="c1"&gt;# view operation history&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;but undo &lt;span class="c1"&gt;# undo the last operation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="conflicts-dont-block-your-flow"&gt;&lt;a href="#conflicts-dont-block-your-flow" class="header-anchor"&gt;&lt;/a&gt;Conflicts Don&amp;rsquo;t Block Your Flow
&lt;/h2&gt;&lt;p&gt;Standard &lt;code&gt;git rebase&lt;/code&gt; stops on the first conflict and waits. Multiple conflicts mean multiple interruptions before the rebase can complete.&lt;/p&gt;
&lt;p&gt;GitButler&amp;rsquo;s &lt;strong&gt;First Class Conflicts&lt;/strong&gt; make rebase always succeed. Conflicted commits are marked and can be resolved later, in any order — they don&amp;rsquo;t block the rest of the work.&lt;/p&gt;
&lt;h2 id="github--gitlab-integration"&gt;&lt;a href="#github--gitlab-integration" class="header-anchor"&gt;&lt;/a&gt;GitHub / GitLab Integration
&lt;/h2&gt;&lt;p&gt;Without leaving GitButler:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open and update PRs&lt;/li&gt;
&lt;li&gt;Check CI status&lt;/li&gt;
&lt;li&gt;Browse branch lists&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CLI:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;but forge pr create &lt;span class="c1"&gt;# open a PR&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;but forge pr list &lt;span class="c1"&gt;# list PRs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="ai-integration"&gt;&lt;a href="#ai-integration" class="header-anchor"&gt;&lt;/a&gt;AI Integration
&lt;/h2&gt;&lt;p&gt;Built-in AI generates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Commit messages&lt;/li&gt;
&lt;li&gt;Branch names&lt;/li&gt;
&lt;li&gt;PR descriptions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also install hooks that let Claude Code or other AI agents manage Git through GitButler directly.&lt;/p&gt;
&lt;h2 id="installation"&gt;&lt;a href="#installation" class="header-anchor"&gt;&lt;/a&gt;Installation
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install gitbutler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# or download the GUI directly&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# https://gitbutler.com/downloads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;but&lt;/code&gt; CLI installs alongside the GUI app.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;but --help
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="how-it-compares-to-git-worktree"&gt;&lt;a href="#how-it-compares-to-git-worktree" class="header-anchor"&gt;&lt;/a&gt;How It Compares to git worktree
&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;ve written before about &lt;a class="link" href="https://recca0120.github.io/en/p/git-worktree-parallel-work/" &gt;using git worktree to work on multiple branches in parallel&lt;/a&gt;. Both solve the &amp;ldquo;parallel work&amp;rdquo; problem, but from different angles:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;git worktree&lt;/th&gt;
 &lt;th&gt;GitButler&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Nature&lt;/td&gt;
 &lt;td&gt;Native Git feature&lt;/td&gt;
 &lt;td&gt;Full Git client&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Interface&lt;/td&gt;
 &lt;td&gt;CLI&lt;/td&gt;
 &lt;td&gt;GUI + CLI&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Parallel branches&lt;/td&gt;
 &lt;td&gt;Multiple directories&lt;/td&gt;
 &lt;td&gt;Single directory&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Commit management&lt;/td&gt;
 &lt;td&gt;Requires rebase -i&lt;/td&gt;
 &lt;td&gt;Drag and drop&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Learning curve&lt;/td&gt;
 &lt;td&gt;Low (works like Git)&lt;/td&gt;
 &lt;td&gt;New UI to learn&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Worktree fits people comfortable with the CLI who want minimal tooling. GitButler fits workflows involving complex commit manipulation or teams who want a polished GUI.&lt;/p&gt;
&lt;h2 id="license"&gt;&lt;a href="#license" class="header-anchor"&gt;&lt;/a&gt;License
&lt;/h2&gt;&lt;p&gt;GitButler uses a &lt;strong&gt;Fair Source&lt;/strong&gt; license — use it, read the source, contribute, but don&amp;rsquo;t build a competing product with it. &lt;strong&gt;It converts to MIT after 2 years&lt;/strong&gt; — open source with an expiring non-compete clause.&lt;/p&gt;
&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/gitbutlerapp/gitbutler" target="_blank" rel="noopener"
 &gt;GitButler GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.gitbutler.com" target="_blank" rel="noopener"
 &gt;GitButler Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://gitbutler.com" target="_blank" rel="noopener"
 &gt;GitButler Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://fair.io/" target="_blank" rel="noopener"
 &gt;Fair Source License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>