Refresh git state after branch switch so SSH projects update the branch name - #61701
Open
kkoshin wants to merge 2 commits into
Open
Refresh git state after branch switch so SSH projects update the branch name#61701kkoshin wants to merge 2 commits into
kkoshin wants to merge 2 commits into
Conversation
…ch name Repository::change_branch relied entirely on the worktree file watcher picking up the .git/HEAD change to re-scan and propagate the new branch. That watcher round-trip is unreliable on remote (SSH) hosts: the switch runs on the server, but the downstream UpdateRepository carrying the new branch_summary never reaches the client, so the UI keeps showing the old branch even though the checkout succeeded (verified in the terminal). Local mode worked only because the local watcher reliably observes .git/HEAD. Mirror reset and fetch, which explicitly refresh after mutating git state instead of trusting the watcher: call schedule_scan(updates_tx, cx) after the change job. On a local repo this re-reads the branch and emits HeadChanged; on the SSH server it sends DownstreamUpdate::UpdateRepository to the client, whose apply_remote_update then emits HeadChanged. schedule_scan is keyed by ReloadGitState, so any watcher-triggered scan is deduped. This required threading cx into change_branch; updated the branch picker, the server-side handle_change_branch, the agent worktree archive caller, and the collab/remote_server integration tests. Added assertions in test_remote_git_branches that the downstream client repository observes the new branch after a remote switch.
Author
|
@cla-bot check |
|
The cla-bot has been summoned, and re-checked this pull request! |
Author
|
@MrSubidubi Thanks! |
Member
|
Thanks for opening a PR. I'd definitely love to understand why our watcher code (or |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
In a remote (SSH) project, clicking a branch in the branch picker switches the branch successfully (verified on the host with
git branch --show-current/cat .git/HEAD), but the branch name shown in Zed's UI never updates. Local projects are unaffected.This is the same family of bugs as #55133 / #13176. Two recent PRs (#59876, #61541) hardened the worktree file watcher so
.gitmetadata changes reliably trigger a git-state reload. After those landed, however, a UI-initiated branch switch in an SSH project still leaves the branch indicator / branch picker stale for me — becausechange_branchitself still relies on the remote host's file watcher catching the.git/HEADwrite, and that round-trip is not reliable on the SSH host in question. This change makes the UI-initiated switch not depend on the watcher, mirroring howresetandfetchalready work.Root cause
Repository::change_branchranbackend.change_branch()(local) or sent aGitChangeBranchRPC (remote) and returned, relying entirely on the worktree file watcher noticing the.git/HEADchange to re-scan and propagate the new branch. On the SSH host that round-trip does not reliably fire, so the server never sends a downstreamUpdateRepositorywith the newbranch_summary, the client'sapply_remote_updatenever emitsHeadChanged, and the UI stays stale until something else touches.git.This is inconsistent with the sibling mutating operations, both of which explicitly refresh git state after the mutation rather than trusting the watcher:
Repository::resetcallsschedule_scan(updates_tx, cx)after the job.Repository::fetchcallsrefresh_branch_list(...)after a successful fetch.change_branchdid neither.Fix
Mirror
reset: makeRepository::change_branchcallschedule_scan(updates_tx, cx)after the change job.schedule_scan(None)→compute_snapshotreads the new branch, emitsHeadChangedlocally.schedule_scan(Some(tx))→compute_snapshotreads the new branch, sendsDownstreamUpdate::UpdateRepositoryover the downstream channel → the client'sapply_remote_updatesees the newbranch_summaryand emitsHeadChanged.GitStoreState::Remote, so no local scan runs; the server does it.schedule_scanis keyed byGitJobKey::ReloadGitState, so any scan additionally triggered by the watcher is deduped — this change is purely additive and never causes a double scan.Because
schedule_scanneedscx: &mut Context<Self>(matchingreset's signature),change_branchnow takescx. Updated the branch picker, the server-sidehandle_change_branch, the agent worktree archive caller, and the collab/remote_server integration tests. Added assertions intest_remote_git_branchesthat the downstream client repository observes the new branch after a remote switch.Because
compute_snapshotrecomputes the full snapshot — branch, HEAD commit, file statuses, and diff stats — the git panel's file list and per-file diff stats refresh together with the branch name, all via the same reliable path.Caveats
.git/HEADwrite after Refresh git state on bare .git events #59876 / worktree: Reload git state when a watcher rescan covers a repository #61541. The motivation for this change is consistency withreset/fetch: an in-app mutating git operation should refresh deterministically rather than depend on the remote watcher. If maintainers would rather chase the watcher root cause, I'm happy to help investigate; this PR is intended as a complementary, low-risk fix that makes the UI action not depend on the watcher at all.Related
Release Notes: