Repository navigation
Stop sending a guessed main as a trail's base - #2886
Merged
Merged
Conversation
With no --base, trail create took origin/HEAD and, when the clone had none, guessed main whenever origin/main existed. It sent that guess, so the server never applied the repo's real default branch. In a repo whose default is develop or release, the trail got base main: Entire's draft targeted main, and the user's own PR into the real default could not settle the trail, which stayed open with the draft re-running CI. When the user was on the default branch, the wrong guess also made the trail reuse that branch itself, so the draft proposed merging the whole default branch into main. The base is now --base, else origin/HEAD, else origin's HEAD read with `git ls-remote --symref` (bounded, non-interactive, validated), else nothing: the server then uses the repo's default branch. Branch naming keeps the local main/master guess when the base is unknown; that guess is never sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Entire-Checkpoint: 01M5R0EEXWT24BA9R6Z8PAWA45
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unchecked local symref targets can still produce incorrect trail bases, and subprocess output capture remains unbounded.
2 open issues
What changed in this PR
This PR separates trail base selection from branch naming so trail creation no longer sends a guessed main that overrides the server’s repository default.
Changes:
- Resolve the base from
--base, localorigin/HEAD, or a bounded remote lookup; otherwise omit it. - Apply the shared resolver to repository and project trails, keeping local guesses only for branch naming.
- Add resolver tests and stub remote lookup in package tests.
| File | Description |
|---|---|
cmd/entire/cli/trail_cmd.go |
Separates the API base from branch-naming input. |
cmd/entire/cli/trail_base.go |
Adds shared local and remote default-branch resolution. |
cmd/entire/cli/trail_base_test.go |
Tests parsing, remote lookup, and base-selection precedence. |
cmd/entire/cli/project_trail_publish.go |
Applies separate base and naming values to project trails. |
cmd/entire/cli/project_trail_publish_test.go |
Expects an omitted base when detection is inconclusive. |
cmd/entire/cli/global_test.go |
Stubs remote default-branch lookup for package tests. |
Review effort: Balanced
A hand-set origin/HEAD pointing outside refs/remotes/origin/ was sent as a literal base; only a branch of origin now counts. The ls-remote lookup capped its output only after git had written it all to memory; both streams now go through limitedWriter, failing on stdout overflow and dropping excess stderr. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Entire-Checkpoint: 01M5R1BFQK7004Y2PFCVX7DXYC
…HEAD fetch leaves an existing origin/HEAD alone when the upstream default changes and the old branch survives, so the local ref could still send the wrong base. Ask origin first and use origin/HEAD only when origin cannot answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XJeHKftfKHD7hSi6ZxJww8 Entire-Checkpoint: 01M673VT0BAZJ62KE71WSQ43SY
Soph
approved these changes
Oct 30, 2026
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.

https://entire.com/gh/entireio/-/trails/2514/changes/cli/1677
Problem
With no
--base,entire trail createused the clone'sorigin/HEAD, and when the clone had none (origin added or re-pointed by hand, older git) it guessedmainwheneverorigin/mainexisted. It sent that guess, so the server never applied the repo's real default branch (trail.base || repo.default_branch).In a repo whose default isn't
main:main, Entire's draft targetsmain, and the user's own PR into the real default can't settle the trail (merge matching needs the same base) — it stays open and the draft keeps re-running CI. This is the root cause behind a customer report of a duplicate draft on already-merged work (entire-api trail 1094 guards a different path to the same symptom).main.Fix
Base =
--base, elseorigin/HEAD, else origin's HEAD fromgit ls-remote --symref origin HEAD(10s bound, non-interactive, output parsed strictly and validated as a branch name), else nothing — the server then uses the repo's default branch. Both create paths (repo trails and project trails) use it. Branch naming keeps the old local main/master guess when the base is unknown; that guess is never sent.The lookup is a package seam stubbed to "unknown" in
TestMain, so no unit test reaches a real remote.Evidence (live, real
entire trail create)Throwaway GitHub repo with default branch
release, clone withoutorigin/HEAD, onrelease:mainreleaserelease(the default itself)base-fix-new-binary(from the title)release → mainbase-fix-new-binary → releasegit ls-remote --symref origin HEADalso verified against a private GitHub remote (release) and anentire://remote (main).Notes / follow-ups
origin/HEAD(default renamed after clone) still wins over the server, as before.GetDefaultBranchNameusers (explain, import, resume) keep the old guess; out of scope (see ENT-129 duplication).--branchor--base.Testing
release, unreachable remote, base selection (explicit / origin/HEAD / remote / unknown / invalid), and the project create payload omitting an unknown base.mise run checkpasses (the claudecode timing test failed only under machine load and passes on rerun).🤖 Generated with Claude Code
Note
Medium Risk
Changes default trail base sent to the API and branch naming inputs for trail create; wrong behavior could mis-target drafts or branches, but logic is bounded, validated, and well-tested.
Overview
Trail create no longer sends a guessed
mainas the API base when--baseis omitted and the real default branch cannot be determined confidently.Resolution is split into what goes to the server vs what drives branch naming. The sent base is
--base, else localorigin/HEAD, elsegit ls-remote --symref(10s timeout, strict parsing, branch-name validation), else empty so the server applies the repo default. The old localmain/masterguess is kept only fornamingBase(e.g.resolveCreateBranch) and is never posted.resolveTrailCreateBasemoves totrail_base.go;entire trail createand project trail publish both use it. Package tests stub remote lookup inTestMain; new unit tests cover symref parsing, remote HEAD, and base-selection cases; project create tests expect an omitted base when lookup is unknown.Reviewed by Cursor Bugbot for commit 6bd3aeb. Configure here.