feat: grove worktree detach / attach (extract a branch & reintegrate it)#31
Merged
Conversation
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>
b763dce to
c70b533
Compare
`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>
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
为 worktree 增加一对互逆的生命周期操作,并把它们(连同 new/rm)收进
grove worktree命名空间。命名:detach / attach
grove worktree detach—— 把主仓当前分支抽出成独立 worktree,主仓切回 basegrove worktree attach <branch>—— 把某 worktree 的分支收回主仓,删掉该 worktree(detach 的逆操作)convert作为detach的隐藏旧别名保留(feat: grove convert CLI subcommand #28 已发布过);absorb未发布,直接改名无需别名命令结构
规范形式
grove worktree {list,new,detach,attach,rm};顶层grove new/detach/attach/rm为隐藏别名(向后兼容),grove convert旧别名仍可用。attach 的数据安全(核心)
pop --index原样还原;失败仍可从 stash reflog 恢复关键修正:默认 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测试
cargo test54 passed,cargo clippyclean.claude不误拦、规范+别名+旧 convert 三种调用、shell-init 语法校验🤖 Generated with Claude Code