From 497d38f3b4b044782b429d12d2f9a76a89e0f582 Mon Sep 17 00:00:00 2001 From: Matt Walters Date: Tue, 17 Feb 2026 10:58:56 -0600 Subject: [PATCH 1/4] refactor(worktree): rename destroy to remove, keep destroy as hidden alias Aligns with git's `git worktree remove` verb. The semantics genuinely overlap (both tear down a worktree), so there's no reason for gratuitous divergence. `destroy` remains as a hidden alias for backward compat. Implements [[tasks/meta-63]] Co-authored-by: Claude --- src/commands/worktree/add.rs | 2 +- src/commands/worktree/cli_types.rs | 3 +++ src/commands/worktree/create.rs | 2 +- src/commands/worktree/exec.rs | 6 +++--- src/commands/worktree/mod.rs | 10 +++++----- src/commands/worktree/{destroy.rs => remove.rs} | 4 ++-- src/main.rs | 1 + 7 files changed, 16 insertions(+), 12 deletions(-) rename src/commands/worktree/{destroy.rs => remove.rs} (95%) diff --git a/src/commands/worktree/add.rs b/src/commands/worktree/add.rs index 4711112..780fd34 100644 --- a/src/commands/worktree/add.rs +++ b/src/commands/worktree/add.rs @@ -19,7 +19,7 @@ pub(crate) fn handle_add(args: AddArgs, verbose: bool, json: bool, strict: bool) if repo_specs.iter().any(|r| r.alias == ".") { anyhow::bail!( "Cannot add '.' to an existing worktree. The meta repo root can only be established at create time.\n\ - Use 'meta worktree destroy {name}' then 'meta worktree create {name} --repo . ...' instead." + Use 'meta worktree remove {name}' then 'meta worktree create {name} --repo . ...' instead." ); } diff --git a/src/commands/worktree/cli_types.rs b/src/commands/worktree/cli_types.rs index 405adf9..c15e46b 100644 --- a/src/commands/worktree/cli_types.rs +++ b/src/commands/worktree/cli_types.rs @@ -13,6 +13,9 @@ pub enum WorktreeCommands { /// Add a repo to an existing worktree set Add(AddArgs), /// Remove a worktree set + Remove(DestroyArgs), + /// Remove a worktree set (alias for remove) + #[command(hide = true)] Destroy(DestroyArgs), /// List all worktree sets List(ListArgs), diff --git a/src/commands/worktree/create.rs b/src/commands/worktree/create.rs index f76718a..e6c0bae 100644 --- a/src/commands/worktree/create.rs +++ b/src/commands/worktree/create.rs @@ -74,7 +74,7 @@ pub(crate) fn handle_create( let wt_dir = worktree_root.join(name); if wt_dir.exists() { anyhow::bail!( - "Worktree '{}' already exists at {}. Use 'meta worktree destroy {}' first.", + "Worktree '{}' already exists at {}. Use 'meta worktree remove {}' first.", name, wt_dir.display(), name diff --git a/src/commands/worktree/exec.rs b/src/commands/worktree/exec.rs index 2e09e14..5da58d6 100644 --- a/src/commands/worktree/exec.rs +++ b/src/commands/worktree/exec.rs @@ -61,15 +61,15 @@ impl Drop for EphemeralGuard { force: true, }; // Ephemeral cleanup uses strict=false to ensure best-effort cleanup - if let Err(e) = super::destroy::handle_destroy(destroy_args, self.verbose, self.json, false) + if let Err(e) = super::remove::handle_remove(destroy_args, self.verbose, self.json, false) { eprintln!( - "{} Failed to destroy ephemeral worktree '{}': {e}", + "{} Failed to remove ephemeral worktree '{}': {e}", "warning:".yellow().bold(), self.name ); eprintln!( - " Run 'meta worktree destroy {} --force' or 'meta worktree prune' to clean up.", + " Run 'meta worktree remove {} --force' or 'meta worktree prune' to clean up.", self.name ); } diff --git a/src/commands/worktree/mod.rs b/src/commands/worktree/mod.rs index b5bab32..fde68cb 100644 --- a/src/commands/worktree/mod.rs +++ b/src/commands/worktree/mod.rs @@ -3,7 +3,7 @@ mod add; pub(crate) mod cli_types; mod create; -mod destroy; +mod remove; mod diff; mod exec; mod list; @@ -93,8 +93,8 @@ fn handle_worktree_command( match command { WorktreeCommands::Create(args) => create::handle_create(args, verbose, json, global_strict), WorktreeCommands::Add(args) => add::handle_add(args, verbose, json, global_strict), - WorktreeCommands::Destroy(args) => { - destroy::handle_destroy(args, verbose, json, global_strict) + WorktreeCommands::Remove(args) | WorktreeCommands::Destroy(args) => { + remove::handle_remove(args, verbose, json, global_strict) } WorktreeCommands::List(args) => list::handle_list(args, verbose, json), WorktreeCommands::Status(args) => status::handle_status(args, verbose, json), @@ -159,7 +159,7 @@ fn write_worktree_help(w: &mut dyn std::io::Write) { let _ = writeln!(w, "COMMANDS:"); let _ = writeln!(w, " create Create a new worktree set"); let _ = writeln!(w, " add Add a repo to an existing worktree set"); - let _ = writeln!(w, " destroy Remove a worktree set"); + let _ = writeln!(w, " remove Remove a worktree set"); let _ = writeln!(w, " list List all worktree sets"); let _ = writeln!(w, " status Show detailed status of a worktree set"); let _ = writeln!(w, " diff Show cross-repo diff vs base branch"); @@ -188,7 +188,7 @@ fn write_worktree_help(w: &mut dyn std::io::Write) { ); let _ = writeln!(w, " --meta Store custom metadata"); let _ = writeln!(w); - let _ = writeln!(w, "DESTROY OPTIONS:"); + let _ = writeln!(w, "REMOVE OPTIONS:"); let _ = writeln!( w, " --force Remove even with uncommitted changes" diff --git a/src/commands/worktree/destroy.rs b/src/commands/worktree/remove.rs similarity index 95% rename from src/commands/worktree/destroy.rs rename to src/commands/worktree/remove.rs index ba10498..4a0bef9 100644 --- a/src/commands/worktree/destroy.rs +++ b/src/commands/worktree/remove.rs @@ -10,7 +10,7 @@ use meta_git_lib::worktree::types::*; use super::cli_types::DestroyArgs; -pub(crate) fn handle_destroy( +pub(crate) fn handle_remove( args: DestroyArgs, verbose: bool, json: bool, @@ -73,7 +73,7 @@ pub(crate) fn handle_destroy( }; println!("{}", serde_json::to_string_pretty(&output)?); } else { - println!("{} Destroyed worktree '{}'", "✓".green(), name.bold()); + println!("{} Removed worktree '{}'", "✓".green(), name.bold()); } Ok(()) } diff --git a/src/main.rs b/src/main.rs index a7f2f83..7d545e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,6 +74,7 @@ fn main() { "git worktree".to_string(), "git worktree create".to_string(), "git worktree add".to_string(), + "git worktree remove".to_string(), "git worktree destroy".to_string(), "git worktree list".to_string(), "git worktree status".to_string(), From fa925fa2a1fb1c83429ff53faea005b1301bed78 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 17 Feb 2026 16:59:48 +0000 Subject: [PATCH 2/4] style: auto-format code --- src/commands/worktree/exec.rs | 3 +-- src/commands/worktree/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/commands/worktree/exec.rs b/src/commands/worktree/exec.rs index 5da58d6..16e1284 100644 --- a/src/commands/worktree/exec.rs +++ b/src/commands/worktree/exec.rs @@ -61,8 +61,7 @@ impl Drop for EphemeralGuard { force: true, }; // Ephemeral cleanup uses strict=false to ensure best-effort cleanup - if let Err(e) = super::remove::handle_remove(destroy_args, self.verbose, self.json, false) - { + if let Err(e) = super::remove::handle_remove(destroy_args, self.verbose, self.json, false) { eprintln!( "{} Failed to remove ephemeral worktree '{}': {e}", "warning:".yellow().bold(), diff --git a/src/commands/worktree/mod.rs b/src/commands/worktree/mod.rs index fde68cb..1731411 100644 --- a/src/commands/worktree/mod.rs +++ b/src/commands/worktree/mod.rs @@ -3,11 +3,11 @@ mod add; pub(crate) mod cli_types; mod create; -mod remove; mod diff; mod exec; mod list; mod prune; +mod remove; mod status; use anyhow::Result; From c8e5b8c30daaa396addd7b5f1059b5a458256781 Mon Sep 17 00:00:00 2001 From: Matt Walters Date: Tue, 17 Feb 2026 11:43:46 -0600 Subject: [PATCH 3/4] fix: update remaining destroy references in ephemeral help text Addresses review feedback: three user-facing strings still referenced "destroy" instead of "remove" in ephemeral worktree help/messages. Co-authored-by: Claude --- src/commands/worktree/cli_types.rs | 2 +- src/commands/worktree/exec.rs | 2 +- src/commands/worktree/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/worktree/cli_types.rs b/src/commands/worktree/cli_types.rs index c15e46b..04d511a 100644 --- a/src/commands/worktree/cli_types.rs +++ b/src/commands/worktree/cli_types.rs @@ -154,7 +154,7 @@ pub struct ExecArgs { #[arg(long)] pub parallel: bool, - /// Atomic create+exec+destroy (requires --all or --repo, and -- ) + /// Atomic create+exec+remove (requires --all or --repo, and -- ) #[arg(long)] pub ephemeral: bool, diff --git a/src/commands/worktree/exec.rs b/src/commands/worktree/exec.rs index 16e1284..1ff9e75 100644 --- a/src/commands/worktree/exec.rs +++ b/src/commands/worktree/exec.rs @@ -54,7 +54,7 @@ struct EphemeralGuard { impl Drop for EphemeralGuard { fn drop(&mut self) { if self.verbose { - eprintln!("Destroying ephemeral worktree '{}'...", self.name); + eprintln!("Removing ephemeral worktree '{}'...", self.name); } let destroy_args = DestroyArgs { name: self.name.clone(), diff --git a/src/commands/worktree/mod.rs b/src/commands/worktree/mod.rs index 1731411..60c564c 100644 --- a/src/commands/worktree/mod.rs +++ b/src/commands/worktree/mod.rs @@ -198,7 +198,7 @@ fn write_worktree_help(w: &mut dyn std::io::Write) { let _ = writeln!(w, " --include Only run in specified repos"); let _ = writeln!(w, " --exclude Skip specified repos"); let _ = writeln!(w, " --parallel Run commands concurrently"); - let _ = writeln!(w, " --ephemeral Atomic create+exec+destroy"); + let _ = writeln!(w, " --ephemeral Atomic create+exec+remove"); let _ = writeln!(w); let _ = writeln!(w, "DIFF OPTIONS:"); let _ = writeln!( From 578af23d07579939780b19492c3f8a676fb71d3a Mon Sep 17 00:00:00 2001 From: Matt Walters Date: Tue, 17 Feb 2026 12:12:23 -0600 Subject: [PATCH 4/4] fix: update EphemeralGuard doc comment to use remove terminology Co-authored-by: Claude --- src/commands/worktree/exec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/worktree/exec.rs b/src/commands/worktree/exec.rs index 1ff9e75..f901671 100644 --- a/src/commands/worktree/exec.rs +++ b/src/commands/worktree/exec.rs @@ -43,7 +43,7 @@ fn build_loop_config( } } -/// RAII guard that destroys an ephemeral worktree on drop. +/// RAII guard that removes an ephemeral worktree on drop. /// Ensures cleanup even if the exec command panics. struct EphemeralGuard { name: String,