From 8877017ae7f6a2e2761023503e05695f083cad7d Mon Sep 17 00:00:00 2001 From: "Kenneth Benzie (Benie)" Date: Tue, 28 Apr 2026 10:43:06 +0100 Subject: [PATCH] Add worktree sync subcommand This `worktree sync` subcommand follows on from removing symbolic links from `worktree add` to update all worktrees which don't have the latest version of shared files from the root worktree. --- worktree/_worktree | 4 ++++ worktree/worktree.plugin.zsh | 44 ++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/worktree/_worktree b/worktree/_worktree index 91932ab..28670e0 100644 --- a/worktree/_worktree +++ b/worktree/_worktree @@ -32,6 +32,7 @@ _worktree() { 'ls:List managed worktrees' 'remove:Remove a worktree by branch' 'rm:Remove a worktree by branch' + 'sync:Sync copied files from root to worktrees' ) _describe -t commands 'worktree command' commands "$@" ;; @@ -44,6 +45,9 @@ _worktree() { (rm|remove) _arguments '*:: :__worktree_active_branches' ;; + (sync) + _arguments '*:: :__worktree_active_branches' + ;; esac ;; esac diff --git a/worktree/worktree.plugin.zsh b/worktree/worktree.plugin.zsh index f6fd3d9..ae8b640 100644 --- a/worktree/worktree.plugin.zsh +++ b/worktree/worktree.plugin.zsh @@ -1,9 +1,9 @@ worktree() { if [[ "$1" == "" ]]; then - echo "usage: worktree {add,list,remove} [...]" + echo "usage: worktree {add,list,remove,sync} [...]" return 1 elif [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then - echo "usage: worktree {add,list,remove} [...] + echo "usage: worktree {add,list,remove,sync} [...] Manage git worktrees by branch name." return 0 @@ -89,6 +89,46 @@ Manage git worktrees by branch name." done return $failed ;; + sync) + local root=$(git rev-parse --show-toplevel) + local prefix="${root:h}/${root:t}@" + local wt_list + wt_list=$(git worktree list --porcelain) + local branches=("${@:2}") + if (( ${#branches[@]} == 0 )); then + branches=("${(@f)$(echo "$wt_list" | awk -v prefix="$prefix" ' + /^worktree /{ sub(/^worktree /, ""); p=$0 } + /^branch refs\/heads\//{ if(index(p, prefix)==1) { sub(/^branch refs\/heads\//, ""); print } } + ')}") + fi + local failed=0 + local wt_path + for branch in "${branches[@]}"; do + [[ -z "$branch" ]] && continue + wt_path=$(echo "$wt_list" | 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{yellow}warning:%f no worktree for branch: $branch" + failed=1 + continue + fi + if [[ "$wt_path" == "$root" ]]; then + continue + fi + for f in .enter .exit; do + [[ -f "$root/$f" ]] || continue + if [[ -L "$wt_path/$f" ]]; then + rm "$wt_path/$f" + elif [[ -f "$wt_path/$f" ]] && cmp -s "$root/$f" "$wt_path/$f"; then + continue + fi + cp "$root/$f" "$wt_path/$f" + _autoenv_authorized "$wt_path/$f" yes + print -P "%F{green}updated:%f $wt_path/$f" + done + done + return $failed + ;; *) print -P "%F{red}error:%f unknown command: $cmd" return 1