Skip to content

Restore worktree family rows in the repository sidebar#195

Closed
ignatremizov wants to merge 1 commit into
DesktopPlus:mainfrom
ignatremizov:fix/sidebar-worktree-regressions
Closed

Restore worktree family rows in the repository sidebar#195
ignatremizov wants to merge 1 commit into
DesktopPlus:mainfrom
ignatremizov:fix/sidebar-worktree-regressions

Conversation

@ignatremizov

@ignatremizov ignatremizov commented Jun 23, 2026

Copy link
Copy Markdown

Closes #192

Problem

v3.5.13 switched GitHub Desktop Plus to the upstream worktree implementation, but the repository sidebar lost several behaviors that existed in the previous GitHub Desktop Plus worktree implementation:

  • saved main and linked worktree paths can render as duplicate flat repository rows instead of one worktree family
  • filtering no longer reliably matches linked worktree display names / path basenames while keeping the root row above the matching linked rows
  • saved linked worktree rows can cause the same family to be emitted again rather than folding into the Git-discovered family
  • explicitly selecting the parent/root row should switch the current worktree back to the main worktree path
  • recent repository rows should represent the actual recent worktree selection, not expand an entire worktree family

Solution

This keeps the upstream worktree data model and restores the sidebar behavior as a display-layer projection. The grouping code derives worktree families from saved repositories and loaded Git worktree state, keyed by the normalized main worktree path, then renders those families as a root row plus nested linked worktree rows.

This PR is rebased on top of the upstream fixes for worktree-name search, hierarchy-preserving filtered results, and Enter selection. The hierarchy post-processing now groups by worktree family path instead of only repository id, so those upstream behaviors still work when a saved linked worktree row is backed by a different repository id than the root row.

Changes:

  • group saved main and linked worktree repositories into one sidebar family when worktree rows are enabled
  • deduplicate saved linked worktree entries against Git-discovered family rows
  • keep linked worktree rows selectable, searchable, pinnable, context-menuable, and visually distinguishable by branch/path when names collide
  • make synthetic root rows explicitly switch to the main worktree path
  • keep stale/prunable worktree rows actionable and refresh all saved repositories in a worktree family
  • track recent selections by repository id plus selected worktree path, expose a configurable recent count, and show only the selected recent worktree row in Recent
  • preserve filtered repository-list order so parent rows stay above matching linked rows, including saved linked worktree rows with distinct repository ids
  • hide inner virtualized section overflow so large account/org groups do not create nested scrollbars
  • add local Copilot SDK model typings and client construction updates required for this branch to compile against the current SDK package

The intent is not to reintroduce the old persisted data model. The new behavior is derived from existing saved repository entries plus upstream worktree state.

Acceptance Criteria

  • Given a saved root repository with linked worktrees, When the repository sidebar opens, Then the root row appears once and linked worktrees appear as nested rows.
  • Given both the root path and a linked worktree path are saved as repositories, When worktree rows are enabled, Then the sidebar emits one worktree family instead of duplicate families.
  • Given a linked worktree basename or branch matches the filter, When filtering the repository sidebar, Then the matching linked row remains visible under its root row.
  • Given the current worktree is linked, When the user selects the synthetic root row, Then the app switches to the main/root worktree path.
  • Given recent entries include linked worktree selections, When Recent is shown, Then it displays the actual selected worktree rows up to the configured limit.

Risk Assessment

Risk tier: Medium

Affected areas: repository sidebar grouping/filtering, repository selection, worktree context menu actions, recent repository persistence, preferences UI, worktree refresh/prune flow, Copilot SDK compile compatibility.

Coverage added for the main risks:

  • row grouping and deduplication: worktree families, linked-only saved paths, same-name worktrees, stale/prunable rows, pinned families, and Recent worktree paths
  • filtering and hierarchy: linked worktree path/branch search, preserved parent-before-child order, and saved linked rows whose repository id differs from the root row
  • selection dispatch: synthetic root rows switch to the root path; saved linked rows switch through their source/root repository
  • context menu targeting: normal repository rows, linked worktree rows, synthetic root rows, and stale/prunable worktree rows
  • persistence/config migration: path-aware Recent entries and configurable Recent count
  • compile compatibility: Copilot SDK client/model type updates covered by yarn compile:dev

Remaining risk: manual UI density/regression risk in very large sidebar profiles, because the app does not have an end-to-end repository-sidebar fixture that mirrors a real multi-account worktree setup. I validated that manually with a local profile.

Test Plan

Automated:

  • yarn test:unit app/test/unit/section-list-test.ts app/test/unit/ui/section-filter-list-test.tsx app/test/unit/repositories-list-grouping-test.ts app/test/unit/ui/repositories-list-test.ts app/test/unit/ui/repository-list-item-test.tsx app/test/unit/repository-list-item-context-menu-test.ts
  • yarn compile:dev
  • yarn build:prod

Manual QA:

  • Built an unpacked Linux app and verified the sidebar against a local profile with multiple root repositories and linked worktrees.
  • Verified filtering by linked worktree names, nested family rendering, Recent worktree rows, root-row selection, and removal of nested account/org scrollbars.

Screenshots

Omitted for now because the validating profile contains private repository and worktree names. The automated tests use neutral paths/branches for the row-shape and filtering cases. I can add synthetic screenshots if needed.

Release notes

Notes: [Fixed] Restores grouped worktree rows and worktree-name filtering in the repository sidebar

Restore the pre-v3.5.13 repository-list behavior on top of the upstream worktree model without changing the persisted worktree data model. The sidebar now derives a display family from the saved repositories plus the loaded Git worktree state, so a root repository and its linked worktrees render as one grouped family while still selecting the underlying upstream repository/worktree paths.

Changes:
- Expand Git-discovered worktrees as nested repository-list rows under their root/main worktree row when the sidebar worktree setting is enabled.
- Deduplicate saved linked worktree repositories against the derived worktree family so adding a linked worktree does not emit a second copy of the same family.
- Keep linked rows selectable, searchable, pinnable, context-menuable, and visually distinguishable by worktree path/branch when names collide.
- Make synthetic root rows explicitly switch to the main worktree path instead of preserving a previously selected linked worktree path.
- Refresh and prune worktree-family state on startup/removal so stale and prunable rows remain actionable without duplicate Pull all rows.
- Track recent repository selections by repository id plus selected worktree path, expose a configurable recent count, and show only the selected recent worktree row rather than expanding whole families in Recent.
- Preserve filtered row order for the repository sidebar so root rows stay above matching linked rows during searches.
- Hide overflow on inner virtualized section grids so large account/org groups do not create nested scrollbars.
- Add local Copilot SDK model typings and client construction updates required for the branch to compile against the current SDK package.

Validation:
- yarn test:unit app/test/unit/section-list-test.ts app/test/unit/ui/section-filter-list-test.tsx app/test/unit/repositories-list-grouping-test.ts app/test/unit/ui/repositories-list-test.ts app/test/unit/ui/repository-list-item-test.tsx app/test/unit/repository-list-item-context-menu-test.ts
- yarn compile:dev
- yarn build:prod

Behavioral effect:
Searching for a linked worktree name once again surfaces its worktree row under the owning repository family, saved linked worktrees no longer duplicate the family, selecting a parent row switches to the root worktree, and Recent contains the actual recently selected worktree rows with a configurable limit.
@ignatremizov ignatremizov force-pushed the fix/sidebar-worktree-regressions branch from 6605b34 to bf3ec2b Compare June 23, 2026 21:00
@pol-rivero

Copy link
Copy Markdown
Member

@ignatremizov If you don't mind, I'll close this PR as explained here. :)
Additionally, this PR touches a ton of unnecessary files, so that wouldn't be something I would be willing to merge either...

@pol-rivero pol-rivero closed this Jun 23, 2026
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.

Regression: worktree sidebar duplicates repositories and filter no longer matches worktree names

2 participants