From f3f4e78c515530eac591f31be08970035b00deac Mon Sep 17 00:00:00 2001 From: zhangxiang Date: Tue, 18 Aug 2026 14:36:06 +0800 Subject: [PATCH] chore: add script to clean local branches that no longer exist on remote --- git-clean-local-gone.sh | 90 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 git-clean-local-gone.sh diff --git a/git-clean-local-gone.sh b/git-clean-local-gone.sh new file mode 100644 index 0000000..70466ee --- /dev/null +++ b/git-clean-local-gone.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# ============================================================ +# 脚本:git-clean-local-branches.sh +# 功能:删除所有远程不存在的本地分支(只保留当前分支及与远程同名的分支) +# 用法:./git-clean-local-branches.sh [-n|--dry-run] [-f|--force] +# -n, --dry-run 预览要删除的分支,不实际执行 +# -f, --force 跳过确认提示,直接删除 +# ============================================================ + +set -e + +dry_run=false +force=false + +while [[ $# -gt 0 ]]; do + case "$1" in + -n|--dry-run) dry_run=true; shift ;; + -f|--force) force=true; shift ;; + -h|--help) + cat < 刷新所有远程缓存..." +git fetch --all --prune --prune-tags 2>/dev/null || git fetch --all --prune +for remote in $(git remote); do + git remote prune "$remote" 2>/dev/null || true +done +echo + +# ---------- 获取远程分支完整路径(去掉远程前缀) ---------- +# 例如 origin/feat/xxx -> feat/xxx +remote_branches=$(git branch -r | grep -v '\->' | sed 's/^[^/]*\///' | sort -u) + +# ---------- 收集本地分支(排除当前分支) ---------- +current_branch=$(git rev-parse --abbrev-ref HEAD) +to_delete=() +for branch in $(git for-each-ref refs/heads/ --format='%(refname:short)'); do + if [[ "$branch" == "$current_branch" ]]; then + echo " 保留当前分支: $branch" + continue + fi + if ! echo "$remote_branches" | grep -qxF "$branch"; then + to_delete+=("$branch") + fi +done + +# ---------- 执行删除 ---------- +if [[ ${#to_delete[@]} -eq 0 ]]; then + echo "没有需要删除的分支。" + exit 0 +fi + +echo "以下本地分支在远程不存在,将被删除:" +printf " %s\n" "${to_delete[@]}" +echo + +if $dry_run; then + echo "(试运行,未实际删除)" + exit 0 +fi + +if ! $force; then + read -p "确认删除以上分支?(y/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "操作取消。" + exit 0 + fi +fi + +echo "==> 开始删除..." +for branch in "${to_delete[@]}"; do + echo "删除: $branch" + if ! git branch -d "$branch" 2>/dev/null; then + echo " 普通删除失败,尝试强制删除..." + git branch -D "$branch" 2>/dev/null || echo " 警告:删除失败,跳过" + fi +done + +echo "完成。" \ No newline at end of file