Fix Trail Creation Branch Handling and Validation · Entire
Investigate this problem:
The thing that actually broke it was hidden in the very first command’s output: entire trail create couldn’t push the branch to the remote (upstream auth failed … github not linked) but still created the trail anyway and only printed a Warning. That partial success is the trap. From that moment the trail pointed at a branch name that didn’t exist on the remote with my content, so the platform backfilled that branch at main’s tip — and my local branch, the remote branch, and my actual work were three different things.
So, concretely, what was missing in step 1:
GitHub link / auth for the CLI (the real one). The CLI told us: “link your GitHub account at https://entire.io.” Without it, entire trail create’s branch push fails, so the branch is never reflected on the remote. Everything after that is downstream drift. If that push had succeeded, the trail would track my branch and there’s nothing to get confused about.
A commit before creating the trail. I created the trail with my changes still uncommitted. A trail is branch-centric — if the branch has no commit, there’s literally nothing for it to show, and it invites the platform to anchor the branch at main’s tip (empty diff).
An up-to-date base. My local main was stale (4e25b2af) while real main was bf696473. That’s what later turned “push to that branch name” into a non-fast-forward, which I then misread as a name collision.
If those three hold, the flow just works with no rename and no strays:
1
2
3
4
git fetch github main && git checkout -b my-branch github/main # current base
# ...make changes...
git add -A && git commit -m "..." # commit FIRST
entire trail create --branch my-branch --title "..." # pushes my-branch + binds trail
The deeper fix is on the tooling side, not me: entire trail create should hard-fail (or not create the trail) when it can’t push the branch, instead of warning and proceeding. The “Created trail ✓” line after a failed push is exactly what let me move on thinking it worked. Either make the push a precondition, or don’t anchor a backing branch at main’s tip when the user’s branch wasn’t actually delivered.
Short version: I skipped “commit first on current main,” and the CLI’s GitHub link was missing so the branch never reached the remote — but the command reported success, which is what confused me.
Diagnosis
The bug is in runTrailCreate (cmd/entire/cli/trail_cmd.go). The branch push to origin is gated entirely behind if needsCreation:
needsCreation := branchNeedsCreation(repo, branch) // true ONLY if branch is absent LOCALLY
...
if needsCreation { // (A) create local branch
createBranch(...)
}
if needsCreation { // (B) push to origin + hard-fail on push error
...
pushBranchToOrigin(branch)
}
// create the trail on the server — UNCONDITIONAL
client.Post(ctx, trailsBasePath(...), createReq)
branchNeedsCreation returns false whenever the branch already exists locally. So your exact documented flow:
git checkout -b my-branch github/main # branch now exists LOCALLY
git commit ...
entire trail create --branch my-branch # needsCreation == false
...skips block (B) completely. The branch is never pushed, there's no existence check, no warning — yet the trail is still created on the server. The server then has no remote branch to anchor to and backfills my-branch at the base tip. That's the three-way drift (local branch ≠ remote branch ≠ your work), and Created trail ✓ still prints. Your mental model ("trail create pushes my-branch + binds trail") is correct; the code only pushes when it created the branch.
Two notes that refine your write-up:
- The "warn and proceed on push failure" path is already a hard-fail today (lines 661–664) — but only inside the
needsCreationbranch. The genuinely silent path is the existing-branch case, which pushes nothing. - A stale/diverged base would make the push a non-fast-forward; since the push is skipped for existing branches, that failure was never even surfaced.
The fix
Make "the branch reached origin" a precondition for trail creation regardless of whether the CLI created the branch locally — push unconditionally and hard-fail with a clear, auth-aware hint.
Now you implement the platform part in ../entire.io