Created
January 4, 2026 02:49
-
-
Save lukaszraczylo/58c579ec18fb5113d5f3d05a789643ec to your computer and use it in GitHub Desktop.
git worktree helper / manager
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 Manager (bare repo workflow) | |
| # Works in bash and zsh | |
| gwt() { | |
| case "$1" in | |
| init) | |
| shift | |
| _gwt_init "$@" | |
| ;; | |
| add | a) | |
| shift | |
| _gwt_add "$@" | |
| ;; | |
| fork | f) | |
| shift | |
| _gwt_fork "$@" | |
| ;; | |
| jump | j) _gwt_jump ;; | |
| rm) | |
| shift | |
| _gwt_rm "$@" | |
| ;; | |
| ls) _gwt_ls ;; | |
| st) _gwt_st ;; | |
| *) _gwt_help ;; | |
| esac | |
| } | |
| _gwt_root() { | |
| local root | |
| root=$(git rev-parse --git-common-dir 2>/dev/null) | |
| if [[ -z "$root" ]] || [[ "$root" == "." ]]; then | |
| if [[ -f "HEAD" ]] && [[ -d "objects" ]] && [[ -d "refs" ]]; then | |
| root=$PWD | |
| else | |
| echo "Not a git repo" >&2 | |
| return 1 | |
| fi | |
| fi | |
| echo "$root" | |
| } | |
| _gwt_init() { | |
| [[ -z "$1" ]] && { | |
| echo "Usage: gwt init <repo> [name]" >&2 | |
| return 1 | |
| } | |
| local repo="$1" | |
| local name="${2:-$(basename "$repo" .git)}" | |
| git clone --bare "$repo" "$name" && cd "$name" || return 1 | |
| git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*' | |
| git fetch origin | |
| local default | |
| default=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null) | |
| default=${default#origin/} | |
| : "${default:=main}" | |
| mkdir -p trees | |
| git worktree add "trees/$default" "$default" | |
| cd "trees/$default" | |
| } | |
| _gwt_add() { | |
| [[ -z "$1" ]] && { | |
| echo "Usage: gwt add <branch> [dir]" >&2 | |
| return 1 | |
| } | |
| local branch="$1" | |
| local name="${2:-$1}" | |
| local root | |
| root=$(_gwt_root) || return 1 | |
| local dir="$root/trees/$name" | |
| mkdir -p "$root/trees" | |
| if git show-ref --verify --quiet "refs/heads/$branch"; then | |
| git worktree add "$dir" "$branch" | |
| elif git show-ref --verify --quiet "refs/remotes/origin/$branch"; then | |
| git worktree add -b "$branch" "$dir" "origin/$branch" | |
| else | |
| git worktree add -b "$branch" "$dir" | |
| fi && cd "$dir" | |
| } | |
| _gwt_fork() { | |
| [[ -z "$1" ]] && { | |
| echo "Usage: gwt fork <new-branch> [dir]" >&2 | |
| return 1 | |
| } | |
| local new_branch="$1" | |
| local name="${2:-$1}" | |
| local root | |
| root=$(_gwt_root) || return 1 | |
| local dir="$root/trees/$name" | |
| mkdir -p "$root/trees" | |
| git worktree add -b "$new_branch" "$dir" && cd "$dir" | |
| } | |
| _gwt_jump() { | |
| command -v fzf >/dev/null || { | |
| echo "fzf required" >&2 | |
| return 1 | |
| } | |
| local root | |
| root=$(_gwt_root) || return 1 | |
| local dir | |
| dir=$(git worktree list | grep "/trees/" | fzf --height=40% --reverse | awk '{print $1}') | |
| [[ -n "$dir" ]] && cd "$dir" | |
| } | |
| _gwt_rm() { | |
| [[ -z "$1" ]] && { | |
| echo "Usage: gwt rm <name>" >&2 | |
| return 1 | |
| } | |
| local root | |
| root=$(_gwt_root) || return 1 | |
| git worktree remove "$root/trees/$1" | |
| } | |
| _gwt_ls() { | |
| local root | |
| root=$(_gwt_root) || return 1 | |
| git --git-dir="$root" worktree list | |
| } | |
| _gwt_st() { | |
| local root | |
| root=$(_gwt_root) || return 1 | |
| for wt in "$root"/trees/*/; do | |
| [[ -f "$wt/.git" ]] || continue | |
| printf "\n\033[1m%s\033[0m\n" "$(basename "${wt%/}")" | |
| git -C "$wt" status -sb | |
| done | |
| } | |
| _gwt_help() { | |
| cat <<'EOF' | |
| Git Worktree Manager (bare repo workflow) | |
| Usage: gwt <command> [args] | |
| Commands: | |
| init <repo> [name] Clone bare repo + setup structure | |
| add <branch> [dir] Add worktree (existing branch or from origin) | |
| fork <branch> [dir] Add worktree branched from current HEAD | |
| jump fzf picker | |
| rm <name> Remove worktree | |
| ls List worktrees | |
| st Status all | |
| Aliases: a=add, f=fork, j=jump | |
| Examples: | |
| gwt init git@github.com:user/repo.git | |
| gwt add feature-x # checkout existing branch | |
| gwt fork spike-idea # new branch from current HEAD | |
| gwt jump # switch worktrees | |
| EOF | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment