Session worktrees are cut from origin/main, not the repo's actual default branch

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 2 comments · opened Aug 2, 2026

Summary

When a session creates a worktree, its branch is cut from origin/main rather than the repository's actual default branch. In a repo whose default branch is not main, every such worktree starts hundreds of commits behind trunk — on a branch whose auto-generated name implies it contains recent work.

worktree.baseRef is documented as defaulting to fresh, which "branches from origin/<default-branch> for a clean tree". That is not the observed behaviour.

Environment

| | |
|---|---|
| Claude Code | 2.1.220 |
| OS | macOS 26.5.2 (arm64) |
| git | 2.50.1 (Apple Git-155) |
| Remote host | GitLab |
| Repo default branch | feat/post-launch-build-queue (not main) |

Expected

New session worktrees branch from origin/feat/post-launch-build-queue — the default branch.

Actual

They branch from 4629183, the tip of origin/main, currently 888 commits behind the default branch and not an ancestor of it.

$ git rev-parse --short origin/main
4629183
$ git rev-list --count 4629183..origin/feat/post-launch-build-queue
888
$ git branch -a --contains 4629183
  main
  remotes/origin/main

Branch-creation evidence from the reflog:

$ git reflog show claude/supabase-billing-analysis-1f51f9 --date=iso
4629183 ...@{2026-07-23 16:52:09}: branch: Created from 462918373f4247d8a34dd061dab05a1383626d7f

At peak this affected 7 of 22 worktrees simultaneously. It is still reproducing: a worktree created 2026-08-03 was 876 commits behind on first use.

This is not user misconfiguration

Both the remote's declared default and the local symbolic ref agree, and have since 2026-07-02 — three weeks before the first affected worktree:

$ git remote show origin | grep 'HEAD branch'
  HEAD branch: feat/post-launch-build-queue

$ git symbolic-ref --short refs/remotes/origin/HEAD
origin/feat/post-launch-build-queue

Ruled out

  • worktree.baseRef override — absent from user, project and local settings (jq '.worktree'null in all three), so the documented fresh default applies.
  • Stale local origin/HEAD — set 2026-07-02, predating every affected worktree.
  • Remote default actually being maingit remote show origin reports the trunk branch live.

Impact

The failure is quiet and it compounds:

  1. The branch name is auto-slugged from the current session's topic, so a worktree named claude/rel-008-handoff-snapshot-… contains none of that work. The name implies currency the base does not have.
  2. In-repo files a session treats as ground truth — TRACKER.md, README, docs — are whatever they were at the stale base. In our case TRACKER.md was four weeks out of date and described work items that had long since shipped.
  3. Nothing surfaces the discrepancy. A session that does not happen to run git rev-list --left-right --count HEAD...origin/HEAD before working will produce confidently wrong output against a month-old view of the repo.

We hit exactly this, and only caught it because the session ran that comparison as its first action. We have since added a local hook that warns at SessionStart and denies the first Edit/Write when HEAD is far behind origin/HEAD — it has fired repeatedly since, which is how we know the behaviour is ongoing rather than a one-off.

Reproduction

Not reproducible on demand from outside — this is reconstructed from the artifacts of independently-created worktrees plus branch reflogs. Suggested check:

  1. Take a repo whose default branch is not main, where main exists and has diverged.
  2. Confirm git remote show origin and git symbolic-ref refs/remotes/origin/HEAD both report the non-main default.
  3. Start a session that creates a worktree.
  4. In the new worktree: git rev-list --left-right --count HEAD...origin/HEAD.

Expected 0 behind; we observe several hundred.

Suggested fix

Resolve the base from origin/HEAD (or the remote's reported default) rather than assuming main. Failing that, warn when a newly created worktree is significantly behind origin/HEAD — the silence is what makes this expensive.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗