From 8138ab95a8a488f94f42fdca4a96f61b8208eccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pacana?= Date: Fri, 31 Jul 2026 09:30:36 +0200 Subject: [PATCH] Keep worktree directories flat * Slug branch names before using them as worktree directory names so branches with slashes do not create nested picker entries. * Keep the real branch name in git and only change the filesystem path, so wtd can still discover the branch from the selected worktree. * Fail when the slug path already exists instead of guessing which branch the user meant. --- modules/claude/worktree-create.sh | 12 +++++++++--- modules/fish.nix | 7 ++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/modules/claude/worktree-create.sh b/modules/claude/worktree-create.sh index 616bc9f..c013563 100644 --- a/modules/claude/worktree-create.sh +++ b/modules/claude/worktree-create.sh @@ -1,6 +1,6 @@ # Runs under writeShellApplication (set -euo pipefail). Claude Code's # WorktreeCreate hook: it fully replaces the default `git worktree add`, so this -# script both places the worktree under ~/Code/worktrees// and copies +# script both places the worktree under ~/Code/worktrees// and copies # local, gitignored config into it. The created path MUST be the last stdout # line; all other output goes to stderr; any non-zero exit aborts creation. @@ -14,7 +14,8 @@ COMMON_DIR=$(git -C "$CWD" rev-parse --path-format=absolute --git-common-dir) MAIN_ROOT=$(dirname "$COMMON_DIR") REPO=$(basename "$MAIN_ROOT") -DEST="$HOME/Code/worktrees/$REPO/$NAME" +SLUG=$(printf '%s' "$NAME" | tr -c '[:alnum:]._-' '-') +DEST="$HOME/Code/worktrees/$REPO/$SLUG" # Base ref: origin's default branch (fresh). Fall back to HEAD if there's no origin. ORIGIN_HEAD=$(git -C "$MAIN_ROOT" symbolic-ref --quiet refs/remotes/origin/HEAD || true) @@ -25,9 +26,14 @@ fi BASE_REF=${ORIGIN_HEAD#refs/remotes/} [ -z "$BASE_REF" ] && BASE_REF=HEAD +if [ -e "$DEST" ]; then + echo "Worktree path already exists: $DEST" >&2 + exit 1 +fi + mkdir -p "$(dirname "$DEST")" -# New branch named after the slug; if it already exists, check it out instead. +# New branch named after the requested name; if it already exists, check it out instead. if git -C "$MAIN_ROOT" show-ref --verify --quiet "refs/heads/$NAME"; then git -C "$MAIN_ROOT" worktree add "$DEST" "$NAME" >&2 else diff --git a/modules/fish.nix b/modules/fish.nix index ab959d1..24e3d76 100644 --- a/modules/fish.nix +++ b/modules/fish.nix @@ -67,9 +67,14 @@ set -l main_root (dirname "$common_dir") set -l repo (basename "$main_root") - set -l name (string replace -a / - -- "$branch") + set -l name (string replace -ar '[^A-Za-z0-9._-]' - -- "$branch") set -l dest "$HOME/Code/worktrees/$repo/$name" + if test -e "$dest" + echo "Worktree path already exists: $dest" >&2 + return 1 + end + mkdir -p (dirname "$dest") if git -C "$main_root" show-ref --verify --quiet "refs/heads/$branch" -- 2.51.2