Skip to content

Instantly share code, notes, and snippets.

@Fronix
Last active February 22, 2026 12:41
Show Gist options
  • Select an option

  • Save Fronix/fc2082f97cb0c655200e13aa3a48ed19 to your computer and use it in GitHub Desktop.

Select an option

Save Fronix/fc2082f97cb0c655200e13aa3a48ed19 to your computer and use it in GitHub Desktop.
Worktree helpers
# Git worktree helpers
# Add this in .bashrc
# or use a .bashrc.d folder and add a sourcer in your .bashrc then add a worktree-helpers.sh file in that folder
# if [ -d "$HOME/.bashrc.d" ]; then
# for f in "$HOME/.bashrc.d"/*.sh; do
# [ -r "$f" ] && . "$f"
# done
#fi
_wt_usage() {
cat <<'EOF'
Worktree helpers
Commands:
wtn <new-branch> [path]
Add a worktree at [path] and create <new-branch> from the current HEAD.
If [path] is omitted, it defaults to <new-branch>.
wte <branch-or-remote> [path]
Add a worktree for an existing branch.
Accepts either:
- a local branch name, for example: main
- a remote branch ref, for example: origin/main
If a remote branch is given and no local branch exists,
a local tracking branch is created automatically.
If [path] is omitted, it defaults to the local branch name.
wtb <new-branch> <base-branch> [path]
Add a worktree at [path], create <new-branch> starting at <base-branch>.
<base-branch may be a local branch or a remote ref such as origin/main.
If [path] is omitted, it defaults to <new-branch>.
wtrm <path> [--force]
Remove the worktree at <path>.
Use --force to remove even if git reports it as dirty or locked.
wtl
List all worktrees.
Notes:
- Run these commands from inside any worktree of the repository.
- Paths are created relative to the current directory unless absolute.
- No existing directories will be overwritten.
Examples:
wtn feature/login
wte main
wte origin/main ../main
wtb feature/refactor origin/main
wtrm ../feature/login
EOF
}
_wt_die() {
printf '%s\n' "$*" >&2
return 2
}
_wt_need_repo() {
git rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|| _wt_die "Not inside a git worktree."
}
_wt_branch_exists_local() {
git show-ref --verify --quiet "refs/heads/$1"
}
_wt_default_path() {
local branch="$1" path="${2:-}"
if [[ -n "$path" ]]; then
printf '%s' "$path"
else
printf '%s' "$branch"
fi
}
_wt_path_ok() {
local path="$1"
[[ -n "$path" ]] || _wt_die "Path is empty."
[[ "$path" != "-"* ]] || _wt_die "Path must not start with '-': $path"
[[ ! -e "$path" ]] || _wt_die "Path already exists: $path"
}
# New worktree + new branch from HEAD
wtn() {
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" || $# -eq 0 ]]; then
_wt_usage
[[ $# -eq 0 ]] && return 2 || return 0
fi
_wt_need_repo || return
local branch="$1"
local path="$(_wt_default_path "$branch" "${2:-}")"
if _wt_branch_exists_local "$branch"; then
_wt_die "Branch already exists locally: $branch"
return 2
fi
_wt_path_ok "$path" || return
git worktree add -b "$branch" -- "$path"
}
# New worktree + existing local or remote branch
wte() {
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" || $# -eq 0 ]]; then
_wt_usage
[[ $# -eq 0 ]] && return 2 || return 0
fi
_wt_need_repo || return
local ref="$1"
local branch
local path
if [[ "$ref" == */* ]] && git show-ref --verify --quiet "refs/remotes/$ref"; then
branch="${ref#*/}"
else
branch="$ref"
fi
path="$(_wt_default_path "$branch" "${2:-}")"
_wt_path_ok "$path" || return
if _wt_branch_exists_local "$branch"; then
git worktree add -- "$path" "$branch"
return
fi
if git show-ref --verify --quiet "refs/remotes/$ref"; then
git worktree add -b "$branch" -- "$path" "$ref"
return
fi
_wt_die "Branch not found locally or remotely: $ref"
return 2
}
# New worktree + new branch based on an existing branch or ref
wtb() {
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" || $# -lt 2 ]]; then
_wt_usage
[[ $# -lt 2 ]] && return 2 || return 0
fi
_wt_need_repo || return
local new_branch="$1"
local base_branch="$2"
local path="$(_wt_default_path "$new_branch" "${3:-}")"
if _wt_branch_exists_local "$new_branch"; then
_wt_die "Branch already exists locally: $new_branch"
return 2
fi
_wt_path_ok "$path" || return
git worktree add -b "$new_branch" -- "$path" "$base_branch"
}
# Remove worktree
wtrm() {
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" || $# -eq 0 ]]; then
_wt_usage
[[ $# -eq 0 ]] && return 2 || return 0
fi
_wt_need_repo || return
local path="$1"
local force_flag=""
if [[ "${2:-}" == "--force" ]]; then
force_flag="--force"
elif [[ -n "${2:-}" ]]; then
_wt_die "Unknown option: $2"
_wt_usage >&2
return 2
fi
git worktree remove $force_flag -- "$path"
}
# List worktrees
wtl() {
git worktree list
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment