fix(workflow): explicit wt-rm + wt-new --no-track (worktree-helper corrections) #43

Merged
oli merged 2 commits from fix/wt-rm-explicit-target into main 2026-06-23 22:42:02 +01:00
Collaborator

Two correctness fixes to the worktree helpers from ADR-0059, both caught on review before real use. Tooling bugfix — no ADR change (the ADR-0059 decisions stand; only the helper implementations are corrected, and ADR-0059's D2 text is updated to match).

1. wt-clean (auto-sweep) → wt-rm <branch> (explicit)

The original wt-clean.sh removed every worktree whose branch was merged into origin/main. But long-lived branches (website, the ci line) are merged into main too — so it would have deleted their worktrees. Auto-detecting what to remove is the footgun.

Replaced with wt-rm <branch> that removes only the branch you name. Safety comes from git's own refusals, not cleverness:

  • won't remove a dirty worktree (no --force);
  • deletes the local branch only if merged into origin/main, else keeps the worktree's removal but preserves the branch + its unmerged commits.

2. wt-new now branches with --no-track

wt-new cut branches off origin/main for a fresh base — but branching off a remote-tracking ref made git set the new branch's upstream to origin/main. A later bare git push then failed with a name-mismatch and suggested the dangerous git push origin HEAD:main (which would push the feature branch straight onto main). --no-track keeps the fresh base without the upstream side-effect; the first git push -u origin <branch> sets the correct one.

Tests (test-first, local origin, no network)

scripts/test-wt.sh16/16, including the properties these fixes are about:

  • wt-rm removes the named worktree and leaves an UNNAMED one untouched;
  • refuses the primary checkout, refuses a dirty worktree, preserves an unmerged branch, errors on an unknown name;
  • a wt-new branch has no upstream.

scripts/test-adr-reserve.sh unchanged → 10/10. All scripts shellcheck-clean. Docs synced in ADR-0059 / CLAUDE.md / the README index.


Cut from main after #41 but before #42, so it edits the 0059 README row + CLAUDE.md; #42 adds the 0058 row + CHANGELOG — different lines, shouldn't conflict with this PR.

Two correctness fixes to the worktree helpers from ADR-0059, both caught on review before real use. Tooling bugfix — no ADR change (the ADR-0059 *decisions* stand; only the helper implementations are corrected, and ADR-0059's D2 text is updated to match). ## 1. `wt-clean` (auto-sweep) → `wt-rm <branch>` (explicit) The original `wt-clean.sh` removed **every** worktree whose branch was merged into `origin/main`. But long-lived branches (`website`, the `ci` line) are merged into `main` too — so it would have **deleted their worktrees**. Auto-detecting *what* to remove is the footgun. Replaced with `wt-rm <branch>` that removes **only the branch you name**. Safety comes from git's own refusals, not cleverness: - won't remove a **dirty** worktree (no `--force`); - deletes the local branch **only if merged into `origin/main`**, else keeps the worktree's removal but preserves the branch + its unmerged commits. ## 2. `wt-new` now branches with `--no-track` `wt-new` cut branches off `origin/main` for a fresh base — but branching off a remote-tracking ref made git set the new branch's **upstream to `origin/main`**. A later bare `git push` then failed with a name-mismatch and suggested the dangerous `git push origin HEAD:main` (which would push the feature branch straight onto `main`). `--no-track` keeps the fresh base without the upstream side-effect; the first `git push -u origin <branch>` sets the correct one. ## Tests (test-first, local `origin`, no network) `scripts/test-wt.sh` → **16/16**, including the properties these fixes are about: - `wt-rm` removes the **named** worktree and leaves an **UNNAMED** one untouched; - refuses the primary checkout, refuses a dirty worktree, **preserves an unmerged branch**, errors on an unknown name; - a `wt-new` branch has **no upstream**. `scripts/test-adr-reserve.sh` unchanged → 10/10. All scripts `shellcheck`-clean. Docs synced in ADR-0059 / `CLAUDE.md` / the README index. --- > Cut from `main` after #41 but before #42, so it edits the `0059` README row + `CLAUDE.md`; #42 adds the `0058` row + `CHANGELOG` — different lines, shouldn't conflict with this PR.
claude-clouddev1 added 2 commits 2026-06-23 22:37:19 +01:00
The first wt-clean.sh removed every worktree whose branch was merged into
origin/main — but long-lived branches (website, the ci line) are merged too,
so it would have deleted their worktrees. Caught on review before any real use.

Replace the auto-sweep with an explicit `wt-rm <branch>` that removes only the
named worktree; safety comes from git's own refusals — it won't remove a dirty
worktree (no --force) and deletes the local branch only when it's merged into
origin/main, otherwise keeps it (and its unmerged commits).

Update test-wt.sh to 15 checks (incl. "unnamed worktree untouched", primary
refused, dirty refused, unmerged branch preserved) and the wt-clean references
in ADR-0059 / CLAUDE.md / the README index.
fix(workflow): wt-new branches with --no-track (no inherited origin/main upstream)
ci / manifests (push) Successful in 4s
ci / gate (push) Successful in 2m6s
ci / gate (pull_request) Successful in 2m3s
ci / manifests (pull_request) Successful in 4s
279ef98ab8
Branching off origin/main set the new branch's upstream to origin/main, so a
bare `git push` failed with a name-mismatch and suggested the dangerous
`git push origin HEAD:main`. Add --no-track so the branch carries no upstream
until the first `git push -u origin <branch>` sets the right one — keeping the
fresh-from-origin/main base without the tracking side-effect.

Add a test-wt.sh assertion that a new branch has no upstream, and note the
behaviour + first-push form in ADR-0059 / CLAUDE.md.
oli merged commit f06ee3b460 into main 2026-06-23 22:42:02 +01:00
oli deleted branch fix/wt-rm-explicit-target 2026-06-23 22:42:02 +01:00
Sign in to join this conversation.