Skip to content

store last selected worktree, and open that when reselecting repo#106

Merged
pol-rivero merged 5 commits into
pol-rivero:mainfrom
coocoo1112:cooperj/storeLastSelectedWorktree
Apr 2, 2026
Merged

store last selected worktree, and open that when reselecting repo#106
pol-rivero merged 5 commits into
pol-rivero:mainfrom
coocoo1112:cooperj/storeLastSelectedWorktree

Conversation

@coocoo1112

@coocoo1112 coocoo1112 commented Mar 26, 2026

Copy link
Copy Markdown

Summary

When working with git worktrees, switching between repositories in the sidebar always lands on the main worktree, even if you were previously working in a linked worktree. This forces you to manually re-select your linked worktree every time you switch repos and come back — a significant friction point for worktree-heavy workflows.

This PR adds automatic worktree restore: the app remembers which worktree you were last using for each repository and automatically switches back to it when you return.

How it works

Preference storage (worktree-preferences.ts — new file)

A small localStorage-backed store keyed by normalized main worktree path. Three operations:

  • setPreferredWorktreePath(mainPath, activePath) — records the user's active worktree. If the active path is the main worktree, the entry is deleted (main is the default, so no preference needed).
  • getPreferredWorktreePath(mainPath) — returns the stored preference, or null to fall back to the main worktree.
  • clearPreferredWorktreePath(mainPath) — removes the entry entirely.

Recording the preference (worktree-dropdown.tsx)

When the user clicks a worktree in the dropdown, setPreferredWorktreePath is called with the main worktree path and the selected worktree path after the repo switch succeeds. This ensures the preference is only persisted once the worktree has been successfully activated.

Restoring the preference (app-store.ts_selectRepository)

When _selectRepository is called for a non-linked repository, the restore logic runs:

  1. Look up the preferred worktree path for this repo.
  2. If one exists and differs from the main worktree path:
    • Check if the linked worktree is already in the repository list — if so, switch to it directly.
    • Otherwise, check if the path still exists on disk. If it does, add it as a repository and switch.
    • If the path no longer exists, clear the stale preference.

This handles all cases: worktree already open, worktree directory exists but not yet added, and worktree was deleted outside the app.

Bug fixes

1. Stale preference after deletion of the currently-active worktree (delete-worktree-dialog.tsx)

Problem: The preference cleanup code called getMainWorktreePath(repository) after removeWorktree() had already deleted the worktree from disk. When deleting the currently-active worktree, the code intentionally skipped the git call (the worktree is gone) and fell back to repository.path — which is the linked worktree path, not the main worktree path. Since preferences are keyed by the main worktree path, the lookup found nothing and the stale preference survived.

Impact: This is a correctness/hygiene issue rather than a user-facing bug. The restore logic in _selectRepository already handles this gracefully — when it encounters a preferred path that no longer exists on disk, it clears the stale entry and falls back to the main worktree. So the preference self-heals on next visit, but lingers in localStorage until then.

Fix: Resolve the main worktree path before the removeWorktree() call while git metadata is still intact, and use that cached value in the cleanup afterward. The isDeletingCurrentWorktree ternary is no longer needed.

2. Worktree dropdown not refreshed after deleting a non-current worktree (delete-worktree-dialog.tsx)

Problem: After deleting a worktree that is not the currently selected one, the dialog dismissed without refreshing the repository state. The worktree dropdown continued showing the deleted worktree until the user switched away and back. Clicking the stale entry produced an "isn't a Git repository" error.

Fix: Added await dispatcher.refreshRepository(repository) after the successful removeWorktree() call in the non-current-worktree path. This triggers gitStore.loadWorktrees(), which updates the dropdown immediately. The current-worktree deletion path doesn't need this because dispatcher.selectRepository(mainRepo) already triggers a full refresh.

3. Preference cleanup when a repository is removed from the app (app-store.ts_removeRepository)

Problem: If a user removes a repository from GitHub Desktop (right-click → Remove), the localStorage entry for that repo's preferred worktree persisted forever with no cleanup path.

Fix: Added cleanup logic in _removeRepository after successful removal:

  • Removing a linked worktree: Searches the repository list for the main worktree whose preference points to the removed path, and clears it.
  • Removing a main worktree: Directly clears the preference keyed by that path.

Files changed

File Change
app/src/lib/worktree-preferences.ts New file — localStorage-backed preference store
app/src/ui/toolbar/worktree-dropdown.tsx Record preference when user clicks a worktree
app/src/lib/stores/app-store.ts Restore preference in _selectRepository; clean up in _removeRepository
app/src/ui/worktrees/delete-worktree-dialog.tsx Fix main-path resolution timing; refresh dropdown after deletion; clean up preference for deleted worktree

@ignatremizov

Copy link
Copy Markdown

#105 might be interesting for you

@coocoo1112

coocoo1112 commented Mar 27, 2026

Copy link
Copy Markdown
Author

#105 might be interesting for you

Cool yeah didn't see that, that looks good too! Something like this still might be valuable to have if people don't want to show the worktrees in the sidebar, e.g. if most of their repos only have one main worktree that they care about. But I'll leave that choice up to y'all, I'm fine either way.

@pol-rivero

Copy link
Copy Markdown
Owner

This currently has a small bug where returning to the main worktree from a linked worktree seems to do nothing the first time. On the second attempt it works fine.

screenrecording-2026-03-27_21-53-47.mp4

@coocoo1112

Copy link
Copy Markdown
Author

This currently has a small bug where returning to the main worktree from a linked worktree seems to do nothing the first time. On the second attempt it works fine.

Ty! just pushed a small change that should fix it

@pol-rivero

Copy link
Copy Markdown
Owner

Everything looks good now, thank you!

@pol-rivero pol-rivero merged commit 23ce8ac into pol-rivero:main Apr 2, 2026
18 checks passed
@pol-rivero

Copy link
Copy Markdown
Owner

This is now available in v3.5.7

pol-rivero added a commit that referenced this pull request Jun 14, 2026
This fix seems to be no longer needed under the new worktrees data structure

Reverts 23ce8ac
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.

Switching away and back to repo with workspaces resets selected worktree

3 participants