gendesign/scripts/cleanup-merged-worktrees.sh

71 lines
2.5 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Cleanup merged Claude Code background-session worktrees.
#
# `claude agents` / `claude --bg` создают `.claude/worktrees/agent-*` для
# каждой background session. После merge PR worktree остаётся locked
# и не удаляется автоматически — за неделю накапливаются десятки.
#
# Скрипт сравнивает branch каждого worktree с `forgejo/main`; если branch
# полностью в main (merged) — удаляет worktree с `--force` (worktree
# заперт супервизором). Затем `git worktree prune` чистит references.
#
# Запускать вручную или через cron (weekly recommended):
# 0 9 * * MON cd /path/to/gendesign && ./scripts/cleanup-merged-worktrees.sh
#
# Safe:
# - Не трогает unmerged branches (in-progress work, PR ещё не merged)
# - Не трогает worktree.lock с твоими running sessions (force нужен только
# потому что Claude Code ставит lock автоматически)
# - Логи action — каждый удалённый branch выводится отдельной строкой
#
# Reference: https://code.claude.com/docs/en/worktrees#clean-up-worktrees
set -e
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$REPO_ROOT"
echo "Fetching forgejo/main..."
git fetch forgejo main --quiet
BEFORE=$(git worktree list | wc -l)
SIZE_BEFORE=$(du -sh .claude/worktrees/ 2>/dev/null | awk '{print $1}')
echo "Scanning $((BEFORE - 1)) worktrees (skip main)..."
REMOVED=0
KEPT=0
# Parse `git worktree list --porcelain` into "path branch" pairs.
git worktree list --porcelain | awk '/^worktree/{w=$2} /^branch/{b=$2} /^$/{print w" "b}' | \
while read path branch; do
# Skip main worktree (no branch field) and detached HEADs.
[ -z "$branch" ] && continue
short="${branch#refs/heads/}"
# Don't touch the worktree we're standing in.
if [ "$path" = "$REPO_ROOT" ]; then
continue
fi
if git merge-base --is-ancestor "$short" forgejo/main 2>/dev/null; then
if git worktree remove --force "$path" 2>/dev/null; then
echo " removed: $short"
REMOVED=$((REMOVED + 1))
else
echo " failed: $short ($path)"
fi
else
KEPT=$((KEPT + 1))
fi
done
git worktree prune
AFTER=$(git worktree list | wc -l)
SIZE_AFTER=$(du -sh .claude/worktrees/ 2>/dev/null | awk '{print $1}')
echo ""
echo "Before: $((BEFORE - 1)) worktrees, $SIZE_BEFORE"
echo "After: $((AFTER - 1)) worktrees, $SIZE_AFTER"