My zsh configuration
git clone https://github.com/m-col/zshrc
Files | Refs | Readme

-rw-r--r-- git-worktrees.zsh


      1 case "${WAYLAND_DISPLAY:+wayland}${DISPLAY:+x11}$OSTYPE" in
      2     wayland*)
      3         _copy='wl-copy'
      4         ;;
      5     x11*)
      6         _copy='xclip -selection clipboard'
      7         ;;
      8     darwin*)
      9         _copy=pbcopy
     10         ;;
     11 esac
     12 
     13 # Add a worktree - creates branch from main if it doesn't exist
     14 gw() {
     15     local input="$1"
     16     if [[ -z "$input" ]]; then
     17 	git worktree list
     18         return 1
     19     fi
     20 
     21     local branch="${input##origin/}"
     22     local folder="${branch//\//-}"
     23     echo -n "$folder" | $_copy
     24     local target="../$folder"
     25 
     26     # Check if worktree already exists
     27     if [[ -d "$target" ]]; then
     28         cd "$target"
     29         return
     30     fi
     31     
     32     # Check if branch exists locally
     33     if git show-ref --verify --quiet "refs/heads/$branch"; then
     34         git worktree add "$target" "$branch" && cd "$target"
     35         return
     36     fi
     37     
     38     # Try fetching from remote
     39     if git fetch origin "$branch" 2>/dev/null && \
     40        git worktree add "$target" "$branch" 2>/dev/null; then
     41         cd "$target"
     42         return
     43     fi
     44     
     45     # Branch doesn't exist - create from main
     46     echo "Branch '$branch' not found, creating from main..."
     47     git fetch origin main:main 2>/dev/null || git fetch origin main
     48     git worktree add -b "$branch" "$target" main && cd "$target"
     49 }
     50 
     51 # cd to top-level folder of a worktree if we're inside a subfolder, otherwise cd to main
     52 gw_top_level() {
     53     local root="${HOME}/git/$1"
     54 
     55     # Check if we're inside a subfolder of the repo
     56     if [[ "$PWD" == "$root"/* ]]; then
     57         # Extract path relative to root, then get first component
     58         local relative="${PWD#$root/}"
     59         local subfolder="${relative%%/*}"
     60         cd "$root/$subfolder"
     61     else
     62         cd "$root/main"
     63     fi
     64 }
     65 
     66 # Remove a worktree
     67 gwr() {
     68     if [[ "$(git rev-parse --is-inside-work-tree)" != "true" ]]; then
     69         echo "Not in a worktree"
     70         return 1
     71     fi
     72     cd $(git rev-parse --show-toplevel)
     73     local target="${1:-$(basename "$PWD")}"
     74 
     75     if [[ "$target" == "main" ]]; then
     76         echo "Refusing to remove main worktree"
     77         return 1
     78     fi
     79 
     80     local branch
     81     if [[ -z "$1" ]]; then
     82         # Current directory - get branch before leaving
     83         branch=$(git branch --show-current)
     84         cd ../main && git worktree remove "../$target" && git branch -D "$branch"
     85     else
     86         # Named worktree - get its branch first
     87         branch=$(git -C "../$target" branch --show-current 2>/dev/null)
     88         git worktree remove "../$target" && [[ -n "$branch" ]] && git branch -D "$branch"
     89     fi
     90     git worktree list
     91 }
     92 
     93 # Interactive branch selection with fzf
     94 gwf() {
     95     local branch=$(git branch -a --sort=-committerdate | \
     96         grep -v HEAD | \
     97         sed 's/^[* ]*//' | \
     98         sed 's#remotes/origin/##' | \
     99         awk '!seen[$0]++' | \
    100         fzf --height 40% --reverse --preview 'git log --oneline -10 {}')
    101     [[ -n "$branch" ]] && gwt "$branch"
    102 }
    103 
    104 # Completions
    105 _gw_branches() {
    106     local branches
    107     branches=(${(f)"$(git branch 2>/dev/null | sed 's/^[* ]*//' | sed 's/^[+ ]*//')"})
    108     _describe 'branch' branches
    109 }
    110 
    111 _gwr_worktrees() {
    112     local worktrees
    113     worktrees=(${(f)"$(git worktree list --porcelain 2>/dev/null | grep '^worktree' | awk '{print $2}' | xargs -n1 basename)"})
    114     _describe 'worktree' worktrees
    115 }
    116 
    117 compdef _gw_branches gw
    118 compdef _gwr_worktrees gwr
    119