Skip to content

feat: grove worktree detach / attach (extract a branch & reintegrate it)#31

Merged
rrbe merged 3 commits into
mainfrom
feat/worktree-absorb
Jun 16, 2026
Merged

feat: grove worktree detach / attach (extract a branch & reintegrate it)#31
rrbe merged 3 commits into
mainfrom
feat/worktree-absorb

Conversation

@rrbe

@rrbe rrbe commented Jun 16, 2026

Copy link
Copy Markdown
Owner

为 worktree 增加一对互逆的生命周期操作,并把它们(连同 new/rm)收进 grove worktree 命名空间。

命名:detach / attach

  • grove worktree detach —— 把主仓当前分支抽出成独立 worktree,主仓切回 base
  • grove worktree attach <branch> —— 把某 worktree 的分支收回主仓,删掉该 worktree(detach 的逆操作)
  • convert 作为 detach隐藏旧别名保留(feat: grove convert CLI subcommand #28 已发布过);absorb 未发布,直接改名无需别名
  • help 文案围绕 worktree 措辞,避免和 detached-HEAD 混淆

早期叫 convert/absorb,因不直观改为 detach/attach。第二个 commit 是这次重命名。

命令结构

规范形式 grove worktree {list,new,detach,attach,rm};顶层 grove new/detach/attach/rm 为隐藏别名(向后兼容),grove convert 旧别名仍可用。

attach 的数据安全(核心)

stash -u(目标)→ worktree remove → switch main → stash pop --index
数据 待遇
已提交 commit 共享对象库,零风险
未提交(staged/unstaged/untracked) stash 搬运 + pop --index 原样还原;失败仍可从 stash reflog 恢复
ignored(node_modules/.env) 随目录删,删前列出并确认

关键修正:默认 worktree root 是仓库内的 .claude,主仓 git status 会把 worktree 目录当 untracked → 主仓洁净检查改用 has_tracked_modifications(只看已跟踪改动),因为 git switch 本就保留 untracked。

git helpers

has_tracked_modifications / stash_push_including_untracked / stash_pop_restoring_index / list_ignored

测试

  • 8 个新单测(plan_detach×4、detach_failure×2… plan_attach×4);cargo test 54 passed,cargo clippy clean
  • 端到端实测真实二进制:detach→attach 往返、未提交/未跟踪携带、ignored 删除告警、nested .claude 不误拦、规范+别名+旧 convert 三种调用、shell-init 语法校验

🤖 Generated with Claude Code

Base automatically changed from fix/convert-rollback-hint to main June 16, 2026 02:53
Restructure the worktree lifecycle verbs under `grove worktree`
(list/new/convert/absorb/rm) while keeping hidden top-level aliases
(`grove new`/`convert`/`absorb`/`rm`) for backward compatibility.

Add `grove worktree absorb` — the inverse of `convert`. It removes a
linked worktree and switches the main worktree onto its branch:

  stash -u (target) → worktree remove → switch main → stash pop --index

Data safety, the whole point of the design:
- committed work is never at risk (shared object database)
- uncommitted work (staged/unstaged/untracked) is carried via a stash
  and stays recoverable from the stash reflog even if a later step fails
- ignored files (node_modules/.env/build output) are intentionally not
  carried; absorb lists them and confirms before deleting

The main-clean check uses has_tracked_modifications (tracked changes
only), not is_dirty — untracked files are preserved by `git switch`, and
nested worktree dirs under the default in-repo worktree root (`.claude`)
would otherwise always make main look dirty.

New git helpers: has_tracked_modifications, stash_push_including_untracked,
stash_pop_restoring_index, list_ignored. Shell-init now auto-cds after
`absorb` and the canonical `worktree convert`/`worktree absorb` forms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rrbe rrbe force-pushed the feat/worktree-absorb branch from b763dce to c70b533 Compare June 16, 2026 03:00
`convert`/`absorb` described the mechanism, not the intent, and weren't
memorable. `detach`/`attach` is a clearer inverse pair: detach the current
branch into its own worktree; attach a worktree's branch back onto main.

- `convert` is kept as a hidden legacy alias on `detach` (it shipped in
  #28); `absorb` was unreleased, so it's renamed outright with no alias.
- help text is worded around worktrees (not detached HEAD) to avoid the
  one downside of the `detach` name.
- shell-init auto-cd now covers detach/attach plus the convert alias.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rrbe rrbe changed the title feat: grove worktree absorb (inverse of convert) feat: grove worktree detach / attach (extract a branch & reintegrate it) Jun 16, 2026
When `grove attach`'s `git switch` step fails, the linked worktree is
already removed and the branch's uncommitted work sits in a stash. The
error now points the user at `git switch <branch> && git stash pop`,
matching the recovery guidance already given on the remove/pop failure
paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rrbe rrbe merged commit af1dbe3 into main Jun 16, 2026
3 checks passed
@rrbe rrbe deleted the feat/worktree-absorb branch June 16, 2026 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant