Skip to content

Commit ce5b006

Browse files
marcusgollclaude
andcommitted
feat(worktrees): auto-fetch origin and sync command
- Fetch origin/main before creating worktrees to ensure branches start up-to-date - Create branches from origin/main instead of local main - Add `sync` command to rebase existing worktrees onto latest main - Fixes "branch is out of date" warnings in GitHub PRs Usage: worktree-manager.sh sync <slug> # Rebase worktree onto latest main 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent a8743e8 commit ce5b006

File tree

1 file changed

+106
-2
lines changed

1 file changed

+106
-2
lines changed

.spec-flow/scripts/bash/worktree-manager.sh

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Commands:
1818
remove <slug> Remove worktree
1919
exists <slug> Check if worktree exists (exit 0 if yes)
2020
get-path <slug> Get absolute path to worktree
21+
sync <slug> Rebase worktree branch onto latest main
2122
cleanup [--dry-run] Remove merged/stale worktrees
2223
link-memory <slug> Create symlinks to shared memory
2324
@@ -163,12 +164,26 @@ PY
163164

164165
local worktree_path="$type_dir/$slug"
165166

167+
# Fetch latest from origin to ensure we're up to date (v11.8.4)
168+
log_info "Fetching latest from origin..."
169+
git fetch origin --quiet 2>/dev/null || log_warn "Could not fetch from origin (working offline?)"
170+
171+
# Determine base branch (origin/main or origin/master)
172+
local base_branch="origin/main"
173+
if ! git rev-parse --verify --quiet "$base_branch" >/dev/null 2>&1; then
174+
base_branch="origin/master"
175+
if ! git rev-parse --verify --quiet "$base_branch" >/dev/null 2>&1; then
176+
base_branch="HEAD" # Fallback to current HEAD if no remote
177+
log_warn "No origin/main or origin/master found, using HEAD"
178+
fi
179+
fi
180+
166181
# Create or checkout branch
167182
if branch_exists "$branch"; then
168183
log_info "Branch '$branch' already exists, will link to worktree"
169184
else
170-
log_info "Creating new branch: $branch"
171-
git branch "$branch" 2>/dev/null || log_warn "Branch creation skipped (may already exist)"
185+
log_info "Creating new branch: $branch (from $base_branch)"
186+
git branch "$branch" "$base_branch" 2>/dev/null || log_warn "Branch creation skipped (may already exist)"
172187
fi
173188

174189
# Create worktree
@@ -369,6 +384,92 @@ cmd_get_path() {
369384
fi
370385
}
371386

387+
# ============================================================================
388+
# Command: sync (v11.8.4)
389+
# ============================================================================
390+
391+
cmd_sync() {
392+
if [ $# -lt 1 ]; then
393+
log_error "Usage: worktree-manager.sh sync <slug>"
394+
exit 1
395+
fi
396+
397+
local slug="$1"
398+
ensure_git_repo
399+
400+
if ! worktree_exists "$slug"; then
401+
log_error "Worktree not found: $slug"
402+
exit 1
403+
fi
404+
405+
local worktree_path
406+
worktree_path=$(get_worktree_path "$slug")
407+
408+
# Fetch latest from origin
409+
log_info "Fetching latest from origin..."
410+
git fetch origin --quiet 2>/dev/null || log_warn "Could not fetch from origin"
411+
412+
# Determine base branch
413+
local base_branch="origin/main"
414+
if ! git rev-parse --verify --quiet "$base_branch" >/dev/null 2>&1; then
415+
base_branch="origin/master"
416+
if ! git rev-parse --verify --quiet "$base_branch" >/dev/null 2>&1; then
417+
log_error "No origin/main or origin/master found"
418+
exit 1
419+
fi
420+
fi
421+
422+
# Get current branch in worktree
423+
local current_branch
424+
current_branch=$(get_worktree_branch "$worktree_path")
425+
426+
# Check if worktree is clean
427+
if ! is_worktree_clean "$worktree_path"; then
428+
log_error "Worktree has uncommitted changes. Commit or stash first."
429+
exit 1
430+
fi
431+
432+
# Check how far behind we are
433+
local behind_count
434+
behind_count=$(cd "$worktree_path" && git rev-list --count HEAD.."$base_branch" 2>/dev/null || echo "0")
435+
436+
if [ "$behind_count" = "0" ]; then
437+
log_success "Branch is already up to date with $base_branch"
438+
if $JSON_OUT; then
439+
echo '{"status": "up-to-date", "behind": 0}'
440+
fi
441+
return 0
442+
fi
443+
444+
log_info "Branch is $behind_count commits behind $base_branch"
445+
446+
if $DRY_RUN; then
447+
log_info "[DRY-RUN] Would rebase $current_branch onto $base_branch"
448+
if $JSON_OUT; then
449+
echo "{\"status\": \"dry-run\", \"behind\": $behind_count, \"base\": \"$base_branch\"}"
450+
fi
451+
return 0
452+
fi
453+
454+
# Perform rebase
455+
log_info "Rebasing $current_branch onto $base_branch..."
456+
cd "$worktree_path" || exit 1
457+
458+
if git rebase "$base_branch" 2>/dev/null; then
459+
log_success "Successfully rebased onto $base_branch"
460+
if $JSON_OUT; then
461+
echo "{\"status\": \"rebased\", \"behind\": 0, \"base\": \"$base_branch\"}"
462+
fi
463+
else
464+
log_error "Rebase failed. Resolve conflicts in $worktree_path then run 'git rebase --continue'"
465+
git rebase --abort 2>/dev/null || true
466+
if $JSON_OUT; then
467+
echo "{\"status\": \"conflict\", \"behind\": $behind_count, \"base\": \"$base_branch\"}"
468+
fi
469+
exit 1
470+
fi
471+
}
472+
372473
# ============================================================================
373474
# Command: cleanup
374475
# ============================================================================
@@ -531,6 +632,9 @@ case "$COMMAND" in
531632
get-path)
532633
cmd_get_path "$@"
533634
;;
635+
sync)
636+
cmd_sync "$@"
637+
;;
534638
cleanup)
535639
cmd_cleanup "$@"
536640
;;

0 commit comments

Comments
 (0)