Skip to content

fix(git): push publishes a branch that tracks a local branch - #33581

Open
Marve10s wants to merge 3 commits into
pingdotgg:mainfrom
Marve10s:fix/push-local-upstream
Open

Marve10s wants to merge 3 commits into
pingdotgg:mainfrom
Marve10s:fix/push-local-upstream

Conversation

@Marve10s

@Marve10s Marve10s commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Push and Commit & push fail for a branch that tracks another local branch. Git stores that as branch.<name>.remote = ., which git switch -c child --track main sets, and which T3's own create-branch step sets when the user has branch.autoSetupMerge=always. T3 runs a bare git push, Git refuses it with exit 128, and the user sees only "Git command exited with a non-zero status." Nothing is published.

When the local parent's name has a slash, such as feature/base, the push succeeds but T3 records t3-merge-base = base and t3-merge-base-ref = refs/remotes/feature/base. Neither exists, so the parent is lost as the comparison and PR base. If the first segment of the parent's name matches a real remote, as with parent upstream/feature/x beside a remote named upstream, the push goes to that remote.

Change

readCurrentUpstreamRef strips refs/heads/ the same way as refs/remotes/, so pushCurrentBranch parsed a local upstream as a remote ref. pushCurrentBranch now checks for remote . before that parse and takes the path a differently named remote upstream already takes: it publishes the branch under its own name to the push remote and keeps the upstream as the base.

A local-tracking branch always publishes under its full local name, so a branch literally named origin/main that tracks local main publishes as origin/main and does not advance remote main.

The base is recorded as the full local name with t3-merge-base-ref = refs/heads/<name>, which resolvePrBase already accepts, and only when no base is recorded. With no remote configured, the push returns the existing "no git remote" error. Remote-upstream behavior is unchanged.

Scope and approval

This is a focused fix for an obvious bug in one function, with no new option or API. The comment on this path states the rule ("Differently named upstreams are bases, not publish targets"), and a local upstream missed it by accident. #29670 and #30563 fixed the same . configuration for status and PR lookup, so this covers the remaining push path. There is no linked issue.

Open PRs #29619, #24047, and #33557 change nearby lines for other problems. None handles a live local upstream, so expect textual conflicts only.

Verification

I reproduced this with real Git repositories and bare remotes through the real driver.

Before, on v0.1.7 and on main, with identical output:

NO-SLASH pushed: {"_tag":"Failure","failure":{"_tag":"GitCommandError","operation":"GitVcsDriver.pushCurrentBranch.push","exitCode":128,"stderrLength":499,"detail":"Git command exited with a non-zero status."}}
NO-SLASH origin branches: [ 'main' ]
AUTOSETUP branch.topic.remote: "." merge: "refs/heads/main"
AUTOSETUP pushed: {"_tag":"Failure","failure":{"_tag":"GitCommandError","operation":"GitVcsDriver.pushCurrentBranch.push","exitCode":128,"stderrLength":499,"detail":"Git command exited with a non-zero status."}}
AUTOSETUP origin branches: [ 'main' ]
SLASH pushed: {"_tag":"Success","value":{"status":"pushed","branch":"child","upstreamBranch":"origin/child","setUpstream":true}}
SLASH t3-merge-base: "base"
SLASH t3-merge-base-ref: "refs/remotes/feature/base"
Tests  3 failed (3)

After, on this branch, the same three checks assert that the branch reaches origin under its own name and that the base is the full local parent:

Test Files  1 passed (1)
     Tests  3 passed (3)

The new rows in GitVcsDriverCore.test.ts cover no-slash and slash parents, remote-name collisions, autoSetupMerge=always through createRef, recorded bases, and no remote. With the source change reverted, 9 of the 12 focused cases from the first commit fail, and the other 3 are existing remote-upstream controls. With it restored, all 12 pass. A follow-up test covers the origin/main branch name: it failed with the push landing on remote main (upstreamBranch origin/main), and passes now.

vp run check:changed passed lint, knip, and typecheck. Three tests in GitVcsDriverCore.test.ts fail on this macOS machine with or without this change: "keeps generated worktree folders short without changing long branch names", "reports each commit hook finishing with its exit code", and "reports the exit code of a commit hook that rejects the commit". I left the full server suite to CI. A local-tracking branch with no commits beyond its parent still reports skipped_up_to_date; that is existing behavior and this PR does not change it.

Implemented with GPT-6.1 Sol in Codex through T3 Code.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-09T22:19:18.980144Z 7ace5f4 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Nov 9, 2026
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Resolved
@macroscopeapp

macroscopeapp Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — This fixes publishing branches that track local parents and preserves their comparison bases. The unresolved finding identifies a case where publishing origin/main instead advances shared remote main; that remote-write risk needs resolution.

Needs human approval because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

pushCurrentBranch now handles branches with local upstreams when resolving push destinations and recording comparison bases. Tests cover push configuration, local and remote tracking bases, published branch names, and preview comparisons.

Changes: Local upstream publishing

Layer / File(s) Summary
Local upstream push handling
apps/server/src/vcs/GitVcsDriverCore.ts, apps/server/src/vcs/GitVcsDriverCore.test.ts
For branches with local upstreams, push destination resolution selects a configured remote and publishes under the local branch name. If no destination is available, push handling reports a missing-remote error. Tests cover push setup and publication with local and remote tracking bases.
Comparison-base recording
apps/server/src/vcs/GitVcsDriverCore.ts, apps/server/src/vcs/GitVcsDriverCore.test.ts
Local upstream comparison refs use refs/heads/<branch>, while remote upstream refs retain refs/remotes/<upstreamRef>. Tests cover merge-base settings, published branch names, and preview comparisons.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant GitVcsDriverCore
  participant LocalGitRepository
  participant ConfiguredPushRemote
  GitVcsDriverCore->>LocalGitRepository: Read local upstream and push configuration
  GitVcsDriverCore->>ConfiguredPushRemote: Publish branch under its local name
Loading

Possibly related issues

Possibly related PRs

  • pingdotgg/t3code#32298: This PR resolves configured Changes bases and preserves explicit t3-merge-base-ref settings; this change records local tracking parents in merge-base configuration.
  • pingdotgg/t3code#33846: Both PRs change how push publication maps local branch names to remote destinations.

Suggested labels: bugfix

Suggested reviewers: juliusmarminge

Merge Risk: Minimal · up to 68933

Pushing a branch that tracks a local branch now publishes it under its full local name and records the correct base. No actionable merge-blocking risk remains beyond normal CI.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title clearly summarizes the main change: publishing branches that track a local branch.
Description check Passed The description includes the required Problem, Change, Scope and approval, and Verification sections. It explains the behavior, justifies the focused fix without a linked issue, and reports focused te…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes the required Problem, Change, Scope and approval, and Verification sections. It explains the behavior, justifies the focused fix without a linked issue, and reports focused tests, checks, and known limitations.

Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 7ace5f4 and 6893368.

Files selected for processing: 2

  • apps/server/src/vcs/GitVcsDriverCore.test.ts
  • apps/server/src/vcs/GitVcsDriverCore.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@maria-rcks

maria-rcks commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified head 7ace5f4ac5a9ddef34b47c4ba1e15a48459e7449 on linux with the real dev web app, repository Playwright, /usr/bin/google-chrome, and real Codex gpt-6.1-sol turns through the local proxy. no mocks or seeded fixtures. the project and conversation were created in the app; Codex created the scenario commits in a real repository with a local bare origin.

on github/main (4c924ff4e6), git action options → push failed for child tracking local main, one commit ahead. the app reported GitVcsDriver.pushCurrentBranch.push; origin still contained only main. after stopping main and starting the exact pr head with the same repository and conversation, the same click published child successfully.

also exercised through the app:

  • commit in the commit dialog, then push to the newly established remote upstream.
  • publish slash-child tracking local feature/base; Changes showed refs/heads/feature/base and only the one added line.
  • publish local origin/main tracking local main; it reached remote origin/main, leaving remote main unchanged.

read-only git inspection after the ui actions:

first push:
  branch.child.remote = origin
  branch.child.merge = refs/heads/child
  branch.child.t3-merge-base = main
  branch.child.t3-merge-base-ref = refs/heads/main
second push:
  origin child = 9e62c92 (feat: add feature two)
slash parent:
  branch.slash-child.t3-merge-base = feature/base
  branch.slash-child.t3-merge-base-ref = refs/heads/feature/base
remote refs after all cases:
  main        5f37a8493f46bababbc5e29135f465f9bc0f22a3 (unchanged)
  child       9e62c92f83bc160a1ea591058fae021ad2660207
  slash-child 057c2c7d009371a8010acebea420d78b5f2e989c
  origin/main 848719c54bcf279f2dd87930d043ff2b880bdd6e

blacksmith: 13 focused push cases passed. vp run check:changed ff7aa5ace311c70587631dcedb43f1d92068c342 passed format, lint, knip, graphql, typecheck, and 257 tests after fetching the base history into the worker. no source changes were needed.

main: push fails on the local-tracking child

pr: the same child publishes successfully

pr: push menu interaction and successful publication

Not verified

native ios/android clients, the electron shell, macos/windows, relay/tunnel connections, and authenticated network pushes to an external git host were not exercised on this linux vm. real git transport used a local bare origin. the combined commit-and-push shortcut was not exercised; commit and push were exercised separately. the no-remote and remote-name-collision matrix cases were covered by existing runtime tests on blacksmith, not separate ui runs.

Takeover update (claude-opus-5-5, head 68933681e6)

Merged current main (no rebase). main moved push routing into resolvePushDestination (#33695), which conflicted with this change. I moved the local-upstream path into that resolver with the same behavior:

  • A branch with branch.<name>.remote = . publishes under its full local name to the push remote.
  • It records t3-merge-base-ref = refs/heads/<parent>.
  • With no remote, it returns the existing "no git remote" error.

resolvePushTarget now reports the same destination for these branches. All of the PR's tests pass unchanged. GitVcsDriverCore.test.ts and GitManager.test.ts pass (386 tests), and vp run check:changed passes.

The Macroscope finding about origin/main landing on remote main was filed against the first commit. 7ace5f4 fixed it, and the merge keeps that fix.

# Conflicts:
#	apps/server/src/vcs/GitVcsDriverCore.ts
@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Nov 10, 2026

This branch has not been deployed

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

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants