git-sync-cleanup — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited git-sync-cleanup (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
ローカルリポジトリを origin の最新に追従させ、リモート側で削除済みのローカルブランチを掃除するためのスキル。日々の作業開始時や、長期開発の合間にローカルが散らかってきたタイミングで使う。
origin という名前のリモートが存在し、認証済みで git fetch / git pull が可能なことorigin 上に main または master のいずれかのブランチが存在することリモートは `origin` 固定 で扱う。複数リモートを運用していても、このスキルは origin のみを対象に fetch / prune / pull する。他リモートの掃除をしたい場合はユーザーが個別に指示する想定。[Step 1: 環境の確認]
→ [Step 2: 未コミット変更の検出(あれば中断)]
→ [Step 3: ベースブランチの検出と切り替え]
→ [Step 4: fetch --prune で全 ref prune → base を fast-forward 取り込み]
→ [Step 5: 削除候補(upstream が gone のブランチ)の検出]
→ [Step 6: 削除対象一覧の提示と一括承認]
→ [Step 7: 一括削除(未マージは保護してリスト報告)]
→ [Step 8: 結果サマリ]ユーザー承認が必須なのは Step 6 の 1 箇所のみ。Step 2 で未コミット変更を検出した場合は承認ではなく「中断 → 状況報告 → ユーザーに対応を委ねる」で扱う。
ユーザーが最初のリクエストで「全部 OK」「掃除も含めて全部やって」など事前承認を明言している場合は、Step 6 の確認を 1 行の復唱に省略してよい(例: gone ブランチ 5 件を削除します)。
最初にツールが揃っているかを軽く確認する。
# Git リポジトリか
git rev-parse --is-inside-work-tree
# origin が存在するか
git remote get-url originどちらかが失敗した場合は、その内容をユーザーに報告して中断する。Git リポジトリでない場合は「ここは Git リポジトリではないようです」と素直に伝える(git init は勝手にしない)。origin が無い場合は「origin リモートが見つかりません。リモートを追加してから再実行してください」と案内する。
ユーザーへの最初のテキスト出力で、これから行うことを 1 行で予告すること(例: origin から最新化して、不要なローカルブランチを掃除します)。
ベースブランチに切り替える前に、ワークツリーがクリーンであることを確認する。git switch は変更が衝突しない場合は通すが、git pull も含めて予期せぬ事故を避けるため、未コミット変更がある時点で中断する。勝手に stash / commit / restore はしない。
# 変更の有無を一気に判定
git status --porcelain出力が空ならクリーン。空でなければ以下のように扱う:
git status -sb で取得してそのまま提示する。git stash / git commit / git restore のいずれかで状態を整えてから再実行してください」と案内し、スキルを終了する。git stash push -u -m "git-sync-cleanup auto stash" を実行してから次に進み、最後(Step 8 の前)に git stash pop を試みて結果を報告する。pop が衝突した場合は無理に解消せず、stash 名と状況を伝える。ベースブランチに切り替えた後で git pull が走るため、未追跡ファイルが上書きされるリスクもある。中断のしきい値は「未コミット変更が 少しでも あれば」とする。切り替え先のベースブランチ(main または master)を以下の順で決める。
# 1. origin/HEAD のシンボリックリンクから(最も信頼できる)
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'
# 2. リモート上に main / master が存在するか
git ls-remote --exit-code --heads origin main >/dev/null 2>&1 && echo main
git ls-remote --exit-code --heads origin master >/dev/null 2>&1 && echo master検出ロジック:
git symbolic-ref refs/remotes/origin/HEAD が取れればそれを採用する(origin のデフォルトブランチ)。取れなければ git remote set-head origin -a を 1 度だけ試して再取得してもよい。main → master の順でリモート存在確認をして、最初に見つかったものを採用する。採用したベースブランチを BASE_BRANCH として保持する。
カレントブランチを記憶し、BASE_BRANCH に切り替える。
ORIGINAL_BRANCH=$(git branch --show-current)
# すでに BASE_BRANCH 上にいる場合は switch 不要
if [ "$ORIGINAL_BRANCH" != "$BASE_BRANCH" ]; then
# ローカルに BASE_BRANCH が無ければ origin から作成
if git show-ref --verify --quiet "refs/heads/${BASE_BRANCH}"; then
git switch "${BASE_BRANCH}"
else
git switch -c "${BASE_BRANCH}" "origin/${BASE_BRANCH}"
fi
fiswitch が失敗した場合は、エラー内容をそのまま報告して中断する(force / restore で強行突破しない)。
origin 全体を fetch --prune して base を fast-forward 取り込みorigin の 全 remote-tracking ref を prune し、その上で BASE_BRANCH を最新に追従させる。1 コマンドにまとめず、必ず 2 段に分けること。
# (4-a) origin の全 remote-tracking ref を prune
git fetch --prune origin
# (4-b) base を fast-forward で取り込み
git merge --ff-only "origin/${BASE_BRANCH}"なぜ 2 段に分けるか:
git pull --prune origin "${BASE_BRANCH}" のように refspec を明示すると、その refspec に紐づく remote-tracking ref しか prune されない(origin/${BASE_BRANCH} 以外の origin/* は prune 対象外)。Step 5 で [gone] 判定をするには origin/* 全体が最新化されている必要があるため、ここでは refspec を渡さずに git fetch --prune origin を使う。--ff-only で fast-forward できないなら明示的に失敗させる(merge コミットや勝手な rebase を作らない)。各段の挙動:
origin/* を最新化し、リモートで削除された ref を origin/* から削除する。これにより Step 5 の [gone] 判定が正しく入る。BASE_BRANCH を origin/${BASE_BRANCH} まで fast-forward させる。fast-forward 不可(= ローカル側に独自コミットがある等)の場合はエラーで中断する。中断時の扱い:
BASE_BRANCH 上で直接コミットしているケース。状況をそのまま報告し、ユーザーに対応を委ねる。勝手に `--rebase` / `--no-ff` / `reset --hard` で押し切らない(独自コミットを失うリスクがあるため)。成功したら、取り込んだコミット数を git log "@{1}..HEAD" --oneline | wc -l などで参考までに把握しておくとサマリで使える(必須ではない)。
origin 上で削除されたブランチをトラッキングしているローカルブランチを抽出する。Step 4-a で *`origin/` 全体に対して prune が済んでいる前提**で、以下が確実な検出方法:
git for-each-ref \
--format='%(refname:short)|%(upstream)|%(upstream:track)' \
refs/heads/ \
| awk -F'|' '$2 ~ /^refs\/remotes\/origin\// && $3 == "[gone]" { print $1 }'ポイント:
upstream が refs/remotes/origin/... のものに限定する(他リモート追跡のブランチには触らない)。upstream:track == "[gone]" のものだけを抽出する(upstream 未設定のローカルオンリーなブランチや、ahead/behind のブランチは対象外)。BASE_BRANCH 自身は通常 upstream が存在するため、この抽出には引っかからない。それでも保険として、結果から BASE_BRANCH を除外しておくと安全。抽出結果を GONE_BRANCHES として保持する。
候補が 0 件の場合は Step 6・Step 7 をスキップして Step 8 に進む(その旨を「掃除対象はありませんでした」と簡潔に伝える)。
候補が 1 件以上ある場合、まとめてユーザーに提示し、一括承認を取る。1 ブランチごとの個別確認はしない。
提示フォーマット(例):
リモートで削除済みのローカルブランチが 5 件見つかりました。
- feat/login-validation (last commit: 2026-04-20, abc1234, "validate email format")
- fix/typo-readme (last commit: 2026-04-18, def5678, "fix typo in README")
- chore/update-deps (last commit: 2026-04-15, 9abcdef, "bump axios to 1.7.0")
- feat/dashboard-prototype (last commit: 2026-03-30, 0123456, "wip dashboard")
- hotfix/payment-rounding (last commit: 2026-03-22, 7890abc, "fix rounding error")
これらをまとめて削除します(未マージのものは安全のため自動的に保護してリスト報告します)。進めてよいですか?各ブランチの参考情報は以下で取得する:
git log -1 --format='%cs %h "%s"' "${branch}"ユーザーが承認したら Step 7 に進む。拒否された場合や、特定ブランチだけ残したいと言われた場合は、対象リストから外して再提示するか、そのままスキルを終了する(ユーザーの意図に従う)。
承認された一覧に対して git branch -d を実行する。-d は BASE_BRANCH にマージ済みかを Git が自動判定し、未マージの場合は失敗するため、安全側に倒れる。`-D`(強制削除)は使わない。
DELETED=()
KEPT_UNMERGED=()
KEPT_OTHER=()
for branch in "${GONE_BRANCHES[@]}"; do
if output=$(git branch -d "${branch}" 2>&1); then
DELETED+=("${branch}")
else
# `git branch -d` は未マージ時に "not fully merged" を返す
if echo "${output}" | grep -q "not fully merged"; then
KEPT_UNMERGED+=("${branch}")
else
KEPT_OTHER+=("${branch}|${output}")
fi
fi
done未マージで残ったブランチについては、削除しない。代わりに「リモートでは消えているがローカルではマージされていないため保護しました」とリストで報告する。ユーザーが内容を確認した上で git branch -D <name> を手動で実行する想定。
-d でも not fully merged 以外の理由で失敗した場合(例: ブランチが他の worktree でチェックアウト中など)は、エラー文をそのままサマリに転記する。
Step 6 の承認は「-dでの一括削除」までを含む。未マージブランチを-Dで強制削除するかどうかは別の意思決定であり、ユーザーが明示的に依頼しない限り行わない。
最後に元のブランチ位置に戻すかどうかを判断し、結果を報告する。
ブランチを戻すか:
BASE_BRANCH のままで終わる。ORIGINAL_BRANCH が BASE_BRANCH と異なり、かつ削除されていない(= 現存する)場合は、戻すかをユーザーに 1 行で確認する(例: 元の 'feat/foo' に戻しますか?)。ORIGINAL_BRANCH が今回削除されたブランチに含まれる場合は、戻れないので BASE_BRANCH のままにし、その旨を報告する。サマリ出力(例):
✅ ローカル最新化 & ブランチ掃除が完了しました
- ベースブランチ: main(origin から 3 コミット取り込み)
- カレントブランチ: main(元: feat/login-validation → 削除済みのため main に留まります)
削除済み (3 件):
- feat/login-validation
- fix/typo-readme
- chore/update-deps
保護 (未マージ・2 件):
- feat/dashboard-prototype
- hotfix/payment-rounding
→ 削除する場合は `git branch -D <name>` を手動で実行してください
エラー (0 件):
なしサマリ内の各セクションは件数が 0 でも「なし」と明示的に書く(沈黙すると「やったのか / やってないのか」がぼやけるため)。
この出力をもってスキルを終了する。続けて作業ブランチを切る・PR を出す等は別スキル(create-pr 等)に委ねる。
git pull のマージや git switch の意図せぬ巻き込みでローカル変更を失わないため。勝手に stash / commit / restore しない。upstream / fork 等)には触らない。origin 以外を追跡しているローカルブランチは Step 5 の抽出時点で除外される。BASE_BRANCH を除外しておく。通常は upstream が存在するため引っかからないが、保険として明示的に除外する。git pull が競合した、git switch が失敗した、といった場面で --force / --hard / --rebase で押し切らない。状況をそのまま報告し、ユーザーに対応を委ねる。~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.