diff --git a/CLAUDE.md b/CLAUDE.md index e78e42d..de9c4c0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -284,7 +284,8 @@ operational rules an agent must follow: chore/ refactor/ test/ ci/`) matching the commit type. - **One worktree per branch — never switch the primary checkout.** Start a branch with `scripts/wt-new.sh ` (creates branch off `origin/main` - + a sibling `-worktree-` worktree); remove a finished one + with `--no-track` + a sibling `-worktree-` worktree; first + push is `git push -u origin `); remove a finished one with `scripts/wt-rm.sh ` (removes only the *named* worktree — it never scans or auto-removes, so long-lived branches like `website`/`ci` are never at risk). This prevents the same-directory clobber hazard. diff --git a/docs/adr/0059-dev-workflow.md b/docs/adr/0059-dev-workflow.md index c01f20f..de02db7 100644 --- a/docs/adr/0059-dev-workflow.md +++ b/docs/adr/0059-dev-workflow.md @@ -74,7 +74,10 @@ directory is how work gets clobbered — worktrees make that impossible. Helpers: - **`scripts/wt-new.sh `** — fetch `main`, create the branch off - `origin/main`, and add the sibling worktree; prints its path. + `origin/main` (with `--no-track`, so it doesn't inherit `origin/main` as + upstream — otherwise a bare `git push` errors on the name mismatch and + suggests the dangerous `HEAD:main`), and add the sibling worktree; prints + its path. First push is `git push -u origin `. - **`scripts/wt-rm.sh `** — remove the worktree for the **named** branch, and nothing else. It does **not** scan for "merged" worktrees to auto-remove: long-lived branches (`website`, the `ci` line) are merged diff --git a/scripts/test-wt.sh b/scripts/test-wt.sh index 4b69c60..ac6b65c 100755 --- a/scripts/test-wt.sh +++ b/scripts/test-wt.sh @@ -37,6 +37,10 @@ out="$(run bash "$WT_NEW" feat/thing-one 2>/dev/null)" check "prints target path" "$target1" "$out" check "worktree dir exists" "yes" "$(exists "$target1")" check "worktree on the new branch" "feat/thing-one" "$(git -C "$target1" rev-parse --abbrev-ref HEAD)" +# It must NOT inherit origin/main as upstream (else a bare `git push` errors +# with a name-mismatch and suggests the dangerous `HEAD:main`). No upstream +# until the first `git push -u` sets the right one. +check "new branch has no upstream" "none" "$(git -C "$target1" rev-parse --abbrev-ref '@{upstream}' 2>/dev/null || echo none)" echo "--- wt-new refuses to clobber an existing branch ---" set +e; run bash "$WT_NEW" feat/thing-one >/dev/null 2>&1; rc=$?; set -e diff --git a/scripts/wt-new.sh b/scripts/wt-new.sh index 4391987..50ba890 100755 --- a/scripts/wt-new.sh +++ b/scripts/wt-new.sh @@ -47,7 +47,13 @@ log "fetching origin/main" git fetch --quiet origin main || die "git fetch origin main failed" log "creating branch '$branch' + worktree at $target" -git worktree add --quiet -b "$branch" "$target" origin/main \ +# `--no-track`: branch off origin/main for a fresh base, but DON'T inherit +# origin/main as the upstream. Without this, branching off a remote-tracking +# ref makes git set the new branch's upstream to origin/main, so a later bare +# `git push` fails with a name-mismatch and suggests the dangerous +# `git push origin HEAD:main`. With no upstream, the first `git push -u origin +# ` sets the correct one. +git worktree add --quiet --no-track -b "$branch" "$target" origin/main \ || die "git worktree add failed" log "ready — cd into it:"