Skip to content

[Bug]: Changes totals compare the default branch with origin instead of its upstream #15314

Description

@letrandat

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

The wrong total is shown from apps/web.

Steps to reproduce

  1. Use a checkout with two remotes. origin points at a fork whose default branch is behind the canonical history. A second remote, upstream, points at the canonical repository.
  2. Check out the default branch and set its upstream to the canonical remote: git branch -u upstream/main. Do not set branch.main.gh-merge-base.
  3. Leave the worktree clean. git status should report the branch level with upstream/main, or only behind it.
  4. Open that project in T3 Code and read the Changes row in the thread details panel.

Expected behavior

On the default branch, Changes compares that branch with its own upstream (@{upstream}). In this setup that is upstream/main. A clean checkout with nothing ahead of its upstream shows +0 −0.

The Changes panel starts from that same ref. The Changes row uses the same base as the panel.

A feature branch still compares with the default branch, not with its own remote copy. This report is only about which remote is used when the current branch is compared with the remote copy of itself.

Actual behavior

The automatic base prefers origin whenever that remote exists, and ignores the branch upstream.

  • resolvePrimaryRemoteName in apps/server/src/vcs/GitVcsDriverCore.ts returns origin when origin exists.
  • resolveBaseBranchForNoUpstream builds the base from that remote. On the default branch, allowRemoteOfCurrent selects origin/<branch> (for example origin/main).
  • The function reads branch.<name>.gh-merge-base. It does not read branch.<name>.remote or @{upstream}. git branch -u upstream/main therefore does not change the base. A normal upstream is not the same as gh-merge-base, which T3 writes only on its own push path.
  • Ahead/behind status already uses @{upstream} through resolveCurrentUpstream. The Changes base does not.

readBranchChangeTotals always calls that automatic resolver. Its comment says the thread panel's Changes row uses the same base as the Changes view. The row in apps/web/src/components/GitActionsControl.tsx renders status.branchChanges from that call.

I checked a clean checkout in this setup with git. The diff against the tracking upstream is empty. The diff against origin/main is the whole lag of the fork: thousands of commits and hundreds of thousands of added and removed lines. That is the total the Changes row shows. The worktree has no uncommitted edits.

The Changes panel can select another comparison target. DiffPanel passes that baseRef only into the diff preview. readBranchChangeTotals never receives it, so the +/− row stays on origin/<default> after the panel is corrected.

This is not #7382 or #15023. Those are about which repository gh and project identity use for pull requests. This one is the Changes diff base.

Impact

Major degradation or frequent failure

A default branch that tracks a non-origin remote shows a repository-sized Changes count when the worktree is clean. Commit and review look like the whole tree was edited.

Version or commit

main at 0cfa113be5 (2026-10-03). GitVcsDriverCore.ts, GitActionsControl.tsx, and DiffPanel.tsx match that commit.

Environment

macOS, T3 Code desktop, git checkout with origin plus another remote that the current branch tracks.

Logs or stack traces

None. git status and git diff against the tracking upstream agree with each other. Only T3's automatic base, origin/<default>, produces the large total.

Workaround

In the Changes panel, set the comparison target to the branch upstream, for example upstream/main. That corrects the panel diff. The Changes row keeps the origin total until base resolution follows the branch upstream.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions