Last active
February 22, 2026 12:41
-
-
Save Fronix/fc2082f97cb0c655200e13aa3a48ed19 to your computer and use it in GitHub Desktop.
Worktree helpers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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