93 lines
3 KiB
Bash
93 lines
3 KiB
Bash
branchdel() {
|
|
# branchdel — remove a branch worktree (optional branch arg)
|
|
local branch_arg
|
|
branch_arg="$1"
|
|
local wt_path
|
|
wt_path=$(pwd)
|
|
local common_dir repo_dir
|
|
if ! common_dir=$(git rev-parse --git-common-dir 2>/dev/null); then
|
|
echo "Not inside a git repository." >&2
|
|
return 1
|
|
fi
|
|
if [ "${common_dir#/}" = "$common_dir" ]; then
|
|
common_dir="$(pwd)/$common_dir"
|
|
fi
|
|
repo_dir="${common_dir%%/.git*}"
|
|
if [ -z "$repo_dir" ]; then
|
|
echo "Unable to determine repository root." >&2
|
|
return 1
|
|
fi
|
|
|
|
# determine current branch in this worktree
|
|
local current default_branch branch target_wt
|
|
current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || { echo "Not inside a git repository." >&2; return 1; }
|
|
|
|
default_branch=$(getdefault)
|
|
|
|
# choose branch: provided arg or current
|
|
if [ -z "$branch_arg" ]; then
|
|
branch="$current"
|
|
else
|
|
branch="$branch_arg"
|
|
fi
|
|
# normalize branch name if refs/heads/ was provided
|
|
branch="${branch#refs/heads/}"
|
|
|
|
# don't remove default
|
|
if [ "$branch" = "$default_branch" ] || [ "$branch" = "default" ]; then
|
|
echo "Refusing to remove default branch worktree ($default_branch)." >&2
|
|
return 1
|
|
fi
|
|
|
|
# find the worktree path for the requested branch
|
|
target_wt=$(git -C "$repo_dir" worktree list --porcelain 2>/dev/null | awk -v b="refs/heads/$branch" '
|
|
$1=="worktree" { w=$2 }
|
|
$1=="branch" && $2==b { print w; exit }
|
|
')
|
|
|
|
# if not found in worktree list, check main worktree branch
|
|
if [ -z "$target_wt" ]; then
|
|
local main_branch
|
|
main_branch=$(git -C "$repo_dir" rev-parse --abbrev-ref HEAD 2>/dev/null || true)
|
|
if [ "$main_branch" = "$branch" ]; then
|
|
target_wt="$repo_dir"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$target_wt" ]; then
|
|
echo "No worktree found for branch '$branch'." >&2
|
|
return 1
|
|
fi
|
|
|
|
if [ "$target_wt" = "$repo_dir" ]; then
|
|
echo "Branch '$branch' is the main worktree at '$repo_dir'. Will not delete main worktree." >&2
|
|
return 1
|
|
fi
|
|
|
|
# if we're currently in that branch/worktree, switch to default and cd to repo root first
|
|
if [ "$current" = "$branch" ]; then
|
|
echo "Currently on branch '$branch' in '$wt_path'. Switching to default branch '$default_branch' in main worktree..."
|
|
if declare -f branch >/dev/null 2>&1; then
|
|
branch default || { echo "Failed to switch to default branch" >&2; return 1; }
|
|
else
|
|
git -C "$repo_dir" checkout "$default_branch" || { echo "Failed to checkout default branch" >&2; return 1; }
|
|
fi
|
|
cd "$repo_dir" || { echo "Failed to change directory to repo root: $repo_dir" >&2; return 1; }
|
|
fi
|
|
|
|
echo "Removing worktree at: $target_wt"
|
|
if git -C "$repo_dir" worktree remove "$target_wt" 2>/dev/null; then
|
|
rm -rf -- "$target_wt" 2>/dev/null || true
|
|
echo "Removed worktree: $target_wt"
|
|
return 0
|
|
fi
|
|
# try with --force as a fallback
|
|
if git -C "$repo_dir" worktree remove --force "$target_wt" 2>/dev/null; then
|
|
rm -rf -- "$target_wt" 2>/dev/null || true
|
|
echo "Removed worktree (forced): $target_wt"
|
|
return 0
|
|
fi
|
|
|
|
echo "Failed to remove worktree: $target_wt" >&2
|
|
return 1
|
|
}
|