Skip to content

Add git worktree support#62

Merged
pol-rivero merged 31 commits intopol-rivero:mainfrom
devxoul:worktree-plus
Feb 19, 2026
Merged

Add git worktree support#62
pol-rivero merged 31 commits intopol-rivero:mainfrom
devxoul:worktree-plus

Conversation

@devxoul
Copy link

@devxoul devxoul commented Feb 13, 2026

Summary

Add full git worktree support to GitHub Desktop, allowing users to create, switch between, rename, and delete working trees directly from the toolbar.

Upstream PR: desktop#21607

Changes

  • Git operations layer (lib/git/worktree.ts, models/worktree.ts): listWorktrees, addWorktree, removeWorktree, moveWorktree with porcelain parser and unit tests.
  • Toolbar integration (ui/toolbar/worktree-dropdown.tsx): New WorktreeDropdown component with searchable foldout, accessible via ⌘E / Ctrl+E.
  • Worktree list (ui/worktrees/worktree-list.tsx, worktree-list-item.tsx): Grouped display (Main/Linked) using SectionFilterList.
  • Context menu (ui/worktrees/worktree-list-item-context-menu.ts): Rename, Copy Name, Copy Path, Delete actions.
  • Dialogs: Add, Rename, and Delete worktree dialogs following existing dialog patterns.
  • App wiring: FoldoutType.Worktree, popup types, menu event, dispatcher methods.
  • Auto-remove worktree repos from sidebar when switching away.

Screenshots

List Search Delete
Screenshot 2026-02-12 at 7 19 56 PM Screenshot 2026-02-12 at 7 19 59 PM Screenshot 2026-02-12 at 7 20 04 PM

devxoul and others added 17 commits February 13, 2026 22:18
Created _worktree-dropdown.scss for toolbar button styling and _worktrees.scss for list component styling. Updated WorktreeListItem to use specific worktrees-list-item class. Styling follows existing design system patterns from branches UI.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Added WorktreeDropdown rendering, onWorktreeDropdownStateChanged handler, and AddWorktreeDialog popup rendering. Toolbar button positioned between Branch and PushPull buttons.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
The worktree list was missing height: 100% on its container, causing the SectionList inside to collapse to zero height. The filter input was visible but no list items appeared below it.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
onWorktreeSelected was wired to onWorktreeClick, which closes the foldout and switches repository. SectionFilterList fires onSelectionChanged on every filter keystroke as the selected row shifts, so typing in the filter would immediately close the dropdown. Separated selection tracking (no-op) from click navigation.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Worktree repos added via the dropdown are now tracked and automatically removed from the repository list when the user switches to a different worktree or back to the original repo, keeping the sidebar clean.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@pol-rivero
Copy link
Owner

pol-rivero commented Feb 13, 2026

I agree that this would be a nice addition!

I have some notes:

  • The Worktree foldout should be resizable with the mouse, like the Branch foldout and the Push/Pull button.

  • The worktree list should have a "+ New Worktree" button next to the search box, like the branch list does. In fact, you seem to have created a PopupType.AddWorktree, but you are not using it anywhere.

  • I see there are linter errors, please fix them first.

  • Why Ctrl/Cmd + E to show the Worktree dropdown instead of Ctrl/Cmd + W? The latter seems more intuitive for "Worktrees" and doesn't seem to be currently in use.

  • I think the Worktree foldout should be located between the Repository and Branch foldouts in the desktop-app-toolbar, instead of being to the right of the Branch foldout.

    • The reason I'm suggesting this is that I think the Repository -> Worktree -> Branch hierarchy makes more sense than Repository -> Branch -> Worktree.
    image
  • Repositories with a single worktree probably should not show the Worktree foldout, as it adds a lot of visual clutter for something that 99% of users won't use.

    • This means that the functionality for creating the first worktree could be a bit hard to discover. For this reason, I would recommend creating a new top-level menu between "Repository" and "Branch" called "Worktree", which would have actions for "New Worktree...", "Rename..." and "Delete..." (see the first 3 items in the Branch menu).
    • You don't need to add keyboard shortcuts for these actions, as I think they won't be used often enough to justify it.
    image

@devxoul
Copy link
Author

devxoul commented Feb 15, 2026

Thanks for the detailed review! I've addressed the following in the latest push:

  • Resizable foldout: The worktree dropdown is now resizable with mouse drag, matching the branch foldout pattern (Resizable wrapper, width persistence via localStorage, constraint calculations).
  • "+ New Worktree" button: Added next to the search box using renderPostFilter, wired to the existing PopupType.AddWorktree dialog. Includes the plus icon matching the branch list style.
  • Lint errors: All 5 fixed (unused state field, a11y title attribute, member ordering).

Regarding the remaining items:

  • Shortcut (Ctrl+E vs Ctrl+W): I'd prefer keeping Ctrl+E since Ctrl+W / Cmd+W is the universal "close window/tab" shortcut in most desktop apps and browsers. Rebinding it could conflict with Electron's built-in behavior and break users' muscle memory.
  • Foldout location: I'd prefer keeping the current position (to the right of Branch) to minimize the UI change for existing users. Moving it between Repository and Branch would shift the toolbar layout users are already accustomed to.
  • Hide for single worktree: I think the worktree foldout should follow the same pattern as the branch foldout — the branch dropdown is always visible even when there's only one branch, so the worktree dropdown should behave consistently.

Happy to discuss further if you feel strongly about any of these!

@pol-rivero
Copy link
Owner

pol-rivero commented Feb 15, 2026

Are you sure you have tested the changes properly?

Please don't submit vibe-coded features without making sure they work first.

image
2026-02-15.10-21-21.mp4

devxoul and others added 3 commits February 16, 2026 03:51
- Wire worktreeDropdownWidth through app-state, app-store, and dispatcher
- Wrap worktree toolbar button in Resizable with drag-to-resize support
- Allocate toolbar space with branch-first priority to prevent layout overflow
- Set foldout min-width independently from button constraints

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Render '+ New Worktree' via renderPostFilter alongside the filter input
- Remove unused isCurrentRepoLinkedWorktree state field
- Reorder members to place memoized getGroups before render helpers

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@devxoul
Copy link
Author

devxoul commented Feb 15, 2026

@pol-rivero My bad, apologies. I didn't test enough for the additional works. I've fixed the layout issues.

Screenshot 2026-02-16 at 4 42 03 AM

@pol-rivero
Copy link
Owner

pol-rivero commented Feb 15, 2026

Now it's much better. Thank you for fixing it.

I have some extra nitpicks:

  • The width of the worktree dropdown should expand to fit the foldout width, like it does in the branches foldout:
image image
  • After creating a new worktree, the app should automatically switch to it. This matches the existing behavior in branches, repos, etc.

  • Linked worktrees shouldn't appear in the repo list:

image

devxoul and others added 3 commits February 16, 2026 18:02
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@devxoul
Copy link
Author

devxoul commented Feb 16, 2026

@pol-rivero Thanks for the detailed review. Implement them all.

Screenshot 2026-02-16 at 6 01 52 PM

@pol-rivero
Copy link
Owner

There are still many issues:

  • Creating a workspace is broken, it shows an error dialog with: some-workspace isn't a Git repository.

  • Deleting a worktree leaves the current repo in an inconsistent state.

image And after refreshing: image

Instead, the worktree should be automatically removed from the app and it should switch to the main worktree.

  • The worktree creation dialog should use a RefNameTextBox (like in the branch creation dialog), because we cannot accept space characters.

  • The isLinkedWorktreeSync method should be replaced with a flag in the Repository object, or at least it should be cached. Accessing the filesystem multiple times on every call to renderRepositoryList will be very slow.

@devxoul
Copy link
Author

devxoul commented Feb 16, 2026

@pol-rivero I've applied all the changes and tested them. Here are demos showing everything working on my end. If the issues persist on your side, please provide me the steps to reproduce so that I can investigate.

newworktree.mov
delworktree.mov

On a more personal note: I think we might have different expectations about the contribution process. I see open source as a hobby, and PRs as a starting point that maintainers and contributors refine together. I'm happy to iterate on feedback, and it's also totally fine if you want to adjust things yourself.

But the "last warning" framing felt off to me. I originally built this for my own use and submitted it upstream (desktop#21607) first. And others suggested I contribute it here, so I did in good faith. I'm already happy with my own build, so if this PR doesn't meet your standards or feels like more trouble than it's worth, feel free to close it. No hard feelings.

devxoul and others added 3 commits February 17, 2026 01:27
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@devxoul
Copy link
Author

devxoul commented Feb 16, 2026

btw, I found a scenario where worktree deletion messes up the repo: when deleting the currently selected worktree. The latest commit fixes this.

@pol-rivero
Copy link
Owner

pol-rivero commented Feb 16, 2026

@devxoul I apologize for my previous comment, I was having a bad day and was feeling frustrated and stressed. I shouldn't have said that.

I will review the PR properly in a few days, once everything has calmed down. If there are any errors afterwards I'll fix them myself, no worries.

@devxoul
Copy link
Author

devxoul commented Feb 16, 2026

@pol-rivero I totally understand. We all have those days. No worries at all, and thank you for saying that. Take your time with the review. I'll be around if anything comes up.

This conflict prevents the app from opening on Linux
The previous flow required entering the new directory and optionally the branch name. However, the last directory fragment cannot contain spaces if the branch name is empty.

The new flow requires for a PARENT directory (auto-populated) that can contain spaces and a mandatory branch name. This should be much simpler, as it only requires entering the branch name in a RefNameTextBox, which auto-converts spaces into dashes.
@pol-rivero
Copy link
Owner

Thank you for your understanding and for your patience :)
I somehow found some free time today and wanted to review the PR again.
This time it looks much better. I have made an adjustment to the worktree creation flow here, please review the new commits and pull them into your branch if you agree.

Also, sorry once again for the completely out-of-place comment. I honestly don't know what I was thinking.

@pol-rivero
Copy link
Owner

pol-rivero commented Feb 17, 2026

I'm still not 100% convinced on always showing the worktree foldout for everyone. I think that most users will never use them, and it really adds a lot of clutter.

I wondered if maybe we could show it by default, but add a label + link at the bottom of the worktrees list to hide it. Something like "If you don't use Git workspaces you can [hide this list]".
If the user wants to show it again, they will need to enable it in the app's settings. Maybe we could also show a confirmation dialog when clicking the link.
In repositories that do have linked workspaces, this foldout would always be shown, regardless of the setting, and the text for hiding it would not be available.

image

@Some1Somewhere
Copy link

Excited to see this merged in!
Thank you @devxoul and @pol-rivero for all your work

@devxoul
Copy link
Author

devxoul commented Feb 18, 2026

@pol-rivero No worries at all. You came back and we started something constructive together, that's all good 👍

I reviewed your branch and I think it's definitely better than my version. I rebased your branch and pushed. Please tell me if you prefer merging instead.

And for the display option - that makes sense. What about adding an option to toggle worktree UI? We can consider adding it to menu or preferences.

Screenshot 2026-02-18 at 12 39 30 PM Screenshot 2026-02-18 at 12 40 08 PM

@pol-rivero
Copy link
Owner

I rebased your branch and pushed. Please tell me if you prefer merging instead.

Either is good. I usually merge for simplicity, but I have no preference for one over the other.

What about adding an option to toggle worktree UI? We can consider adding it to menu or preferences.

Yes, the Appearance settings page seems like the right place, as you suggest.

devxoul and others added 2 commits February 18, 2026 16:58
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@devxoul
Copy link
Author

devxoul commented Feb 18, 2026

@pol-rivero Done! I set off as the default value as you suggested.

Off (default) On
Screenshot 2026-02-18 at 4 59 39 PM Screenshot 2026-02-18 at 4 59 46 PM

@simonepri
Copy link

@devxoul kudos for the work on this PR!

@pol-rivero
Copy link
Owner

I've published the stable release, so let's merge this into main for v3.5.6-beta1 🎉

@pol-rivero pol-rivero merged commit 6ee8bdd into pol-rivero:main Feb 19, 2026
@devxoul devxoul deleted the worktree-plus branch February 20, 2026 02:43
@devxoul
Copy link
Author

devxoul commented Feb 20, 2026

@pol-rivero Thanks for your time for reviewing this!

@plpxsk
Copy link

plpxsk commented Feb 24, 2026

@pol-rivero Done! I set off as the default value as you suggested.

Off (default) On
Screenshot 2026-02-18 at 4 59 39 PM Screenshot 2026-02-18 at 4 59 46 PM

Monumental PR!

One issue, however.

Upon fresh install, there is a conflict between the menu and this setting toggle.

I was looking for my cursor-linked worktrees, and saw in menu: View – Show Worktree list (Cmd-E).

But, nothing was happening.

I had to find this note in the PR to know that I had to first enable this in settings.

Suggest keeping the menu for easy worktree discoverability, but probably need to add a note there like "enable in settings" or similar.

@devxoul
Copy link
Author

devxoul commented Feb 25, 2026

@plpxsk Nice catch! That's a missing scenario. I'm think of automatically turning on the worktree settings when user hits "Show Worktress List". This is simple patch so I created PR: #72. Let's wait for @pol-rivero's idea.

@pol-rivero
Copy link
Owner

@devxoul I agree, this should enable the worktree settings. Let's continue the conversation in #72.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants