#!/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 "完成。"