worktree() { if [[ "$1" == "" ]]; then echo "usage: worktree {add,remove} " return 1 elif [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then echo "usage: worktree {add,remove} Manage git worktrees by branch name." return 0 fi local cmd=$1 local branch=$2 if [[ -z "$branch" ]]; then print -P "%F{red}error:%f missing argument" return 1 fi if ! git rev-parse --git-dir &>/dev/null; then print -P "%F{red}error:%f not a git repository" return 1 fi if [[ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" == "true" ]] && \ [[ "$(git rev-parse --absolute-git-dir)" != "$(git rev-parse --show-toplevel)/.git" ]] then print -P "%F{red}error:%f must be run from the main clone, not a worktree" return 1 fi case $cmd in add) local root=$(git rev-parse --show-toplevel) local wt_dest=${root:h}/${root:t}@${branch} git worktree add "$wt_dest" "$branch" ;; rm|remove) local wt_path wt_path=$(git worktree list --porcelain | awk -v b="$branch" \ '/^worktree /{ sub(/^worktree /, ""); p=$0 } /^branch refs\/heads\//{ sub(/^branch refs\/heads\//, ""); if($0==b) print p }') if [[ -z "$wt_path" ]]; then print -P "%F{red}error:%f no worktree for branch: $branch" return 1 fi if [[ -f "$wt_path/BUILD" ]] || [[ -f "$wt_path/WORKSPACE" ]]; then if (( $+commands[bazel] )); then bazel --output_base="$wt_path" clean --expunge elif [[ -x "$wt_path/bazelw" ]]; then "$wt_path/bazelw" clean --expunge fi fi git worktree remove "$wt_path" || return 1 local root=$(git rev-parse --show-toplevel) local parent=${wt_path:h} while [[ "$parent" != "${root:h}" ]] && [[ -d "$parent" ]]; do rmdir "$parent" 2>/dev/null || break parent=${parent:h} done ;; *) print -P "%F{red}error:%f unknown command: $cmd" return 1 ;; esac }