Skip to content

fix(desktop): scope base branch override per workspace#1329

Merged
Kitenite merged 1 commit intomainfrom
kitenite/wrong-git-tracking
Feb 9, 2026
Merged

fix(desktop): scope base branch override per workspace#1329
Kitenite merged 1 commit intomainfrom
kitenite/wrong-git-tracking

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Feb 9, 2026

Summary

  • The baseBranch in the changes Zustand store was a global string | null shared across all workspaces and persisted to localStorage
  • When a user changed the base branch comparison in one workspace's Changes view, it silently affected every other workspace
  • This caused new workspaces to show diff stats against the wrong branch, making it look like a WIP feature was accidentally merged
  • Only reproducible for users who had previously changed the base branch selector — others had null which correctly fell back to the default

Changes

  • stores/changes/store.ts: Changed baseBranch from string | null to Record<string, string | null> keyed by worktreePath. Updated setBaseBranch to accept (worktreePath, branch). Added getBaseBranch(worktreePath) helper.
  • ChangesHeader.tsx: BaseBranchSelector now scopes overrides per worktree. Selecting the default branch resets to null instead of storing the literal string (fixes cross-project stickiness).
  • ChangesView.tsx, ChangesContent.tsx, SidebarControl.tsx: Updated to use getBaseBranch(worktreePath) instead of the old global value.

Test Plan

  • Open workspace A, change base branch to a non-default branch in the Changes sidebar
  • Open workspace B — verify it uses the project default branch, not workspace A's override
  • Restart the app — verify workspace B still uses the default, workspace A retains its override
  • Select the default branch in the base branch dropdown — verify it resets correctly

Summary by CodeRabbit

  • Improvements
    • Base branch is now stored per workspace, improving multi-workspace behavior and reliability.
    • Branch selector persists workspace-specific base branch choices and allows clearing back to default.
    • Status, change lists, and related views now use the workspace-specific base branch for comparisons and listings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 9, 2026

📝 Walkthrough

Walkthrough

Refactors the changes store to hold per-worktree base branches (map keyed by worktreePath), adds get/set per-worktree accessors, migration for persisted state, and updates multiple UI components to call getBaseBranch(worktreePath) and setBaseBranch(worktreePath, ...) instead of a single shared baseBranch.

Changes

Cohort / File(s) Summary
Store Core
apps/desktop/src/renderer/stores/changes/store.ts
Convert baseBranch from `string
Sidebar / Main UI
apps/desktop/src/renderer/screens/main/components/SidebarControl/SidebarControl.tsx
Replace { baseBranch, selectFile } with { getBaseBranch, selectFile } and compute `baseBranch = getBaseBranch(worktreePath
Workspace Changes Content
apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/ChangesContent.tsx
Derive local baseBranch via `getBaseBranch(worktreePath
Right Sidebar — Changes View
apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/ChangesView.tsx
Swap direct store baseBranch access for `getBaseBranch(worktreePath
Changes Header
apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx
Read per-worktree baseBranch via getBaseBranch(worktreePath); update branch selection to call setBaseBranch(worktreePath, branch) or setBaseBranch(worktreePath, null) to clear.

Sequence Diagram(s)

sequenceDiagram
  participant UI as "UI Component"
  participant Store as "ChangesStore\n(get/setBaseBranch)"
  participant Persist as "Persist Layer"
  participant Status as "Status Query / API"

  UI->>Store: getBaseBranch(worktreePath)
  Store-->>UI: baseBranch (string|null)
  UI->>Status: queryStatus(effectiveBaseBranch)
  Status-->>UI: statusResults
  UI->>Store: setBaseBranch(worktreePath, branch|null)
  Store->>Persist: persist updated baseBranch map
  Persist-->>Store: persist OK
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 I hopped through maps of branches new,
Each path now keeps its favored view.
No single trunk to make me frown—
Per-worktree sprouts wear every crown. 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: scoping the base branch override to be per-workspace instead of global.
Description check ✅ Passed The description covers the problem statement, changes made, and test plan, though it uses checklist items without completion status. All required template sections are either addressed or appropriately included.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kitenite/wrong-git-tracking

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
apps/desktop/src/renderer/stores/changes/store.ts (1)

158-163: Guard the migration with a version check to prevent future data loss.

The migrate callback receives the old version as its second parameter, but it's currently ignored. If a version: 2 migration is added later, zustand will invoke this same function with version === 1, and the unconditional state.baseBranch = {} will wipe already-migrated per-worktree data.

Proposed fix
 				version: 1,
-				migrate: (persisted) => {
+				migrate: (persisted, version) => {
 					const state = persisted as Record<string, unknown>;
-					state.baseBranch = {};
+					if (version === 0) {
+						state.baseBranch = {};
+					}
 					return state as unknown as ChangesState;
 				},

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/desktop/src/renderer/stores/changes/store.ts`:
- Line 55: The persisted shape of baseBranch changed from a scalar (string|null)
to a Record<string,string|null>, causing setBaseBranch to spread characters of
old strings into the store; update the persist config for this store to include
a numeric version and a migrate function that detects the old shape (e.g.,
typeof state.baseBranch === "string" or state.baseBranch === null) and converts
it to an empty object {} (or appropriate record) before returning the migrated
state; apply the same migration logic where the store is configured (also
relevant to the other persist block around the code referenced at lines 114-126)
and ensure tests cover hydration from the old scalar format so
setBaseBranch/getBaseBranch behave correctly after migration.

Comment thread apps/desktop/src/renderer/stores/changes/store.ts
@Kitenite Kitenite force-pushed the kitenite/wrong-git-tracking branch from f94c2e7 to 6acae68 Compare February 9, 2026 05:01
The baseBranch in the changes store was a global value shared across all
workspaces. When a user changed the base branch comparison in one
workspace, it affected every other workspace and persisted across
sessions via localStorage. This caused new workspaces to show diff stats
and PR info against the wrong branch.

Make baseBranch a Record keyed by worktreePath so each workspace
maintains its own override. Also fix BaseBranchSelector to reset to null
when the default branch is re-selected.
@Kitenite Kitenite force-pushed the kitenite/wrong-git-tracking branch from 6acae68 to 905e049 Compare February 9, 2026 05:09
@Kitenite Kitenite merged commit d907cee into main Feb 9, 2026
6 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 9, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

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.

1 participant