Use case for GitButler: when you want to run a custom version of an open source project with several fixes. You may have open PRs for them, like I have with the Herdr app:
In the local workspace, both branches are applied at the same time! GitButler calls these parallel branches. This is what but status shows in my local checkout:
$ but status
╭┄ @ [uncommitted] (no changes)
┊
┊╭┄ al [alert-toasts-setting] CI: ✅ #596: feat: a setting turns off agent alert toasts
┊● vxmw feat: a setting turns off agent alert toasts
├╯
┊
┊╭┄ te [terminal-line-height] CI: ✅ #67: feat: terminal line height is a setting
┊◐ zktv feat: terminal line height is a setting
├╯
┊
┊● 903dc81 (upstream: origin/master) 2 new commits (checked 38 seconds ago)
├╯ e77f112 (common base, master) 2026-11-04 fix: let worktree operations wait for large repositories
Hint: ◐ means rewritten locally vs upstream.
Hint: commits are listed newest first. The first token on each line is the ID to use in commands.
Hint: origin/master moved ahead; run `but pull` to update the workspace
alert-toasts-setting and terminal-line-height are separate branches, applied at the same time. GitButler takes care of everything, including rebasing all branches automatically when you advance the base branch. The diff for each branch is ready for a PR. When maintainers request fixes, they just go on the correct branch, no issues. Agents love it! As a bonus you see PRs too.
With only Git, local master would end up with both fixes, and you’d rebase it every time origin/master moves. I can’t even tell where my fixes are here:
$ git log --graph --oneline --decorate -6 master origin/master
* c092833 (HEAD -> master) feat: a setting turns off agent alert toasts
* 78bc337 feat: terminal line height is a setting
* 903dc81 (origin/master) fix: preserve xim input context across focus changes
* 4cf5b50 fix: read one xim message per property so fcitx4 replies are no longer lost on linux (#558)
* e77f112 fix: let worktree operations wait for large repositories
* 1926540 fix: centre sidebar rail items on one line (#453)
If you merge instead, you get a merge commit for each branch, which at least shows the branch name, plus another every time origin/master moves.
$ git log --graph --oneline --decorate -9 master origin/master
* 0c7bc59 (HEAD -> master) Merge remote-tracking branch 'origin/master'
|\
| * 903dc81 (origin/master) fix: preserve xim input context across focus changes
| * 4cf5b50 fix: read one xim message per property so fcitx4 replies are no longer lost on linux (#558)
* | 0837190 Merge branch 'alert-toasts-setting'
|\ \
| * | 312fe4a (alert-toasts-setting) feat: a setting turns off agent alert toasts
| |/
* / 9cb1abf (terminal-line-height) feat: terminal line height is a setting
|/
* e77f112 fix: let worktree operations wait for large repositories
* 1926540 fix: centre sidebar rail items on one line (#453)
* e4906d2 fix: changes list fills the panel and scrolls through every changed file (#474)
With Git, you could also rebase your fixes with origin/master, then apply one by one. Or you could keep them in the same branch, but that makes it annoying to open PRs. There are options, but none of them are great.
I do the same with GitButler itself, since I work there (disclaimer). My local checkout of the GitButler repository runs with all of these branches applied. You can also see some stacks!
$ but status
╭┄ @ [uncommitted] (no changes)
┊
┊╭┄ gp [gpui-folder-stops]
┊● soqm Let the GPUI file list's keys stop on folders
├╯
┊
┊╭┄ pu [gpui-hide-adjacent-hunk-boxes]
┊● mump Hide the hunk box where no lines are left out above it
├╯
┊
┊╭┄ ui [gpui-file-tree-indent]
┊● lrsr Indent a file tree's files a step past their folder
├╯
┊
┊╭┄ fi [filters-headsup-edit-mode]
┊● yuzy Say filters are skipped only while editing or resolving a commit
├╯
┊
┊╭┄ je [gpui-jev-guidance]
┊● uuko Show Jev's review guidance in the GPUI diff
├╯
┊
┊╭┄ ul [pull-keeps-merged-target-history]
┊● sukp Keep a branch's published history when it merged the target
├╯
┊
┊╭┄ ch [checkout-guard-concurrent-changes]
┊● uxtx Guard against changes made while checkout checks the worktree
┊│
┊├┄ he [checkout-undo-failures]
┊● zvor Undo a checkout that fails partway
┊│
┊├┄ ck [checkout-filters-before-worktree] CI: ✅ #17004: Run the worktree filters before touching the worktree
┊● nztk Run the worktree filters before touching the worktree
├╯
┊
┊╭┄ gr:@ [uncommitted] {gpui-grow-context} (no changes)
┊├┄ gr [gpui-grow-context]
┊● mrqu feat(gpui): z grows a hunk's context one scope level, as in deltoids
├╯
┊
┊● 4724d2e8d6 (upstream: origin/master) 2 new commits (checked 9 seconds ago)
├╯ 812107d6d7 (common base, master) 2026-11-05 Merge pull request #17003 from gitbutlerapp/david/gb-2219-resolve-cutting
Hint: commits are listed newest first. The first token on each line is the ID to use in commands.
Hint: origin/master moved ahead; run `but pull` to update the workspace
Hint: gpui-grow-context is behind origin/master; run `but pull` to update it
Comments