Skip to content

refactor(staged): derive PR push button state from git upstream relation#743

Open
matt2e wants to merge 2 commits into
mainfrom
combine-pr-state-and-git-state
Open

refactor(staged): derive PR push button state from git upstream relation#743
matt2e wants to merge 2 commits into
mainfrom
combine-pr-state-and-git-state

Conversation

@matt2e
Copy link
Copy Markdown
Contributor

@matt2e matt2e commented May 20, 2026

Summary

  • Replace the latestCommit.sha !== prHeadSha heuristic in BranchCardPrButton with a new shouldShowPushChanges helper that reads timeline.gitState.upstream.relation (localAhead / diverged => show, inSync / originAhead => hide).
  • Fall back to the old HEAD/PR SHA comparison only when upstream is missing (e.g. fork PRs without an origin/<branch> ref), and bail out entirely when a different branch is checked out so we don't compare unrelated SHAs.
  • After a successful push, refresh local git state instead of optimistically mutating prHeadSha, letting upstream.relation settle back to inSync on its own.
  • Add unit tests covering the in-sync / ahead / behind / diverged / missing-upstream / merged / no-PR / wrong-branch cases.

Test plan

  • pnpm test prButtonGitState (or equivalent vitest run) passes
  • Open a branch with local commits not yet pushed — button shows "Push changes"
  • After pushing, button flips back to its normal state without waiting for a PR poll
  • Merged PR does not show "Push changes"
  • Checking out a different branch on the same project does not surface a spurious "Push changes"

matt2e and others added 2 commits May 19, 2026 13:17
Replaces the SHA comparison in BranchCardPrButton with a small helper
that reads timeline.gitState.upstream.relation, so cases like
originAhead no longer misclassify as "needs push". Falls back to
HEAD/PR SHA comparison only when upstream is missing (fork PRs). After
a successful push, trigger a git-state refresh instead of mutating
prHeadSha optimistically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
When a different branch is checked out (expectedBranchMatches === false),
`upstream.relation` is computed against HEAD's upstream (e.g. main vs
origin/main) and `headSha` belongs to the wrong branch — so the missing-
upstream SHA fallback in shouldShowPushChanges would almost certainly
surface a spurious "needs push". Return false early in that case.

Also adds a default arm with an exhaustiveness assertion so future
additions to UpstreamRelation produce a compile-time error instead of
silently falling through.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
@matt2e matt2e requested review from baxen and wesbillman as code owners May 20, 2026 06:03
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 28935ca17a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +543 to +545
commands.refreshBranchGitState(branch.id).catch((e) => {
console.warn('[Staged] Failed to refresh git state after push:', e);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Force-refresh git state after push completion

After a successful push, this now relies on refreshBranchGitState to flip hasUnpushed back to false, but that command is TTL-gated (FetchMode::Ttl, 30s) and can skip fetching if a refresh ran recently. Because git push does not update refs/remotes/origin/<branch> locally, skipping fetch leaves upstream.relation as localAhead, so the UI can keep showing "Push changes" even though the push succeeded. This is reproducible when the user pushes shortly after any prior git-state refresh.

Useful? React with 👍 / 👎.

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