shell: add worktree branch helpers and link_ignored script; expose branch/branchd aliases
This commit is contained in:
parent
8bbc0f7825
commit
752310e386
2 changed files with 288 additions and 0 deletions
113
common/general/shell/branch.sh
Normal file
113
common/general/shell/branch.sh
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# Branch and branchd helpers (worktree-based)
|
||||
|
||||
# branch <name> — create or jump to a worktree for <name>
|
||||
branch() {
|
||||
# Use XDG_DATA_HOME or default to ~/.local/share
|
||||
local xdg=${XDG_DATA_HOME:-$HOME/.local/share}
|
||||
# Determine the git common dir (points into the main repo's .git)
|
||||
local common_dir
|
||||
common_dir=$(git rev-parse --git-common-dir 2>/dev/null) || {
|
||||
echo "Not inside a git repository." >&2
|
||||
return 1
|
||||
}
|
||||
# Make common_dir absolute if it's relative
|
||||
if [ "${common_dir#/}" = "$common_dir" ]; then
|
||||
common_dir="$(pwd)/$common_dir"
|
||||
fi
|
||||
# repo_dir is the path before '/.git' in the common_dir (handles worktrees)
|
||||
local repo_dir
|
||||
repo_dir="${common_dir%%/.git*}"
|
||||
if [ -z "$repo_dir" ]; then
|
||||
echo "Unable to determine repository root." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local repo_base
|
||||
repo_base=$(basename "$repo_dir")
|
||||
local repo_hash
|
||||
repo_hash=$(printf "%s" "$repo_dir" | sha1sum | awk '{print $1}')
|
||||
|
||||
local branch_name
|
||||
branch_name=$1
|
||||
if [ -z "$branch_name" ]; then
|
||||
echo "Usage: branch <name>" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# If user asked for default or master, cd back to repo root on default branch
|
||||
local default_branch
|
||||
default_branch=$(getdefault 2>/dev/null || echo "")
|
||||
if [ "$branch_name" = "default" ] || [ "$branch_name" = "master" ] || [ "$branch_name" = "$default_branch" ]; then
|
||||
cd "$repo_dir" || return 0
|
||||
git fetch
|
||||
git checkout "$default_branch"
|
||||
pull
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Ensure we have up-to-date remote info
|
||||
git fetch --all --prune
|
||||
|
||||
# If branch exists remotely and not locally, create local branch tracking remote
|
||||
if git ls-remote --exit-code --heads origin "$branch_name" >/dev/null 2>&1; then
|
||||
if ! git show-ref --verify --quiet "refs/heads/$branch_name"; then
|
||||
git branch --track "$branch_name" "origin/$branch_name" 2>/dev/null || git branch "$branch_name" "origin/$branch_name"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Worktree path
|
||||
local wt_root
|
||||
wt_root="$xdg/git_worktrees/${repo_base}_${repo_hash}"
|
||||
local wt_path
|
||||
wt_path="$wt_root/$branch_name"
|
||||
|
||||
mkdir -p "$wt_root"
|
||||
|
||||
# If worktree already exists at our expected path, cd to it
|
||||
if [ -d "$wt_path/.git" ]; then
|
||||
cd "$wt_path" || return 0
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If a worktree for this branch is already registered elsewhere, find it and cd
|
||||
local existing
|
||||
existing=$(git worktree list --porcelain 2>/dev/null | awk -v b="$branch_name" 'BEGIN{RS=""} $0 ~ "refs/heads/"b{for(i=1;i<=NF;i++) if ($i ~ /^worktree/) print $2 }')
|
||||
if [ -n "$existing" ]; then
|
||||
cd "$existing" || return 0
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Create the worktree
|
||||
mkdir -p "$wt_path"
|
||||
git worktree add -B "$branch_name" "$wt_path" "origin/$branch_name" 2>/dev/null || git worktree add "$wt_path" "$branch_name"
|
||||
cd "$wt_path" || return 0
|
||||
}
|
||||
|
||||
# branchd — remove current branch worktree
|
||||
branchd() {
|
||||
local current
|
||||
current=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) || {
|
||||
echo "Not inside a git repository." >&2
|
||||
return 1
|
||||
}
|
||||
local default_branch
|
||||
default_branch=$(getdefault 2>/dev/null || echo "")
|
||||
|
||||
if [ "$current" = "$default_branch" ] || [ "$current" = "default" ]; then
|
||||
echo "Already on default branch ($default_branch). Won't remove." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Find the worktree path for the current branch
|
||||
local wt_path
|
||||
wt_path=$(git worktree list --porcelain 2>/dev/null | awk -v b="$current" 'BEGIN{RS="";FS="\n"} $0 ~ "refs/heads/"b{for(i=1;i<=NF;i++) if ($i ~ /^worktree /) { sub(/^worktree /,"",$i); print $i }}')
|
||||
if [ -z "$wt_path" ]; then
|
||||
echo "Worktree for branch '$current' not found." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Switch to default branch (uses branch() helper) and then remove worktree
|
||||
branch default || { echo "Failed to switch to default branch" >&2; return 1; }
|
||||
|
||||
git worktree remove "$wt_path"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue