You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用bash脚本删除无打开Pull Request的旧Git分支

Bash脚本实现自动清理无关联打开PR的旧分支

下面提供两种可直接使用的实现方案,优先推荐使用GitHub CLI的方案,逻辑更简单不易出错。

方案1:基于GitHub CLI实现(推荐)

前置依赖

  • 已安装GitHub CLI,可通过包管理器直接安装,例如brew install gh/apt install gh
  • 已执行gh auth login完成目标仓库的权限认证

完整脚本

#!/bin/bash
# 配置项
REMOTE_NAME="origin"
# 保护分支,不会被删除
PROTECTED_BRANCHES=("main" "master" "develop" "release/*")
# 分支闲置时间阈值,单位:天,超过该时间无更新才会被清理
INACTIVE_DAYS=30
# dry_run模式:设为true只会打印要删除的分支,设为false会真实执行删除
DRY_RUN=true

# 1. 拉取最新远程信息
git fetch $REMOTE_NAME --prune

# 2. 获取所有打开的PR的源分支列表,去重
OPEN_PR_BRANCHES=($(gh pr list --state open --json headRefName --jq '.[].headRefName' | sort -u))

# 3. 遍历所有远程分支过滤待清理项
for branch in $(git branch -r | grep "$REMOTE_NAME/" | sed "s/$REMOTE_NAME\///"); do
  # 跳过保护分支
  skip=0
  for protected in "${PROTECTED_BRANCHES[@]}"; do
    if [[ $branch == $protected ]]; then
      skip=1
      break
    fi
  done
  if [[ $skip == 1 ]]; then continue; fi

  # 跳过有打开PR关联的分支
  if [[ " ${OPEN_PR_BRANCHES[*]} " =~ " $branch " ]]; then
    continue
  fi

  # 检查分支最后提交时间是否超过闲置阈值
  last_commit_timestamp=$(git log -1 --format=%ct "$REMOTE_NAME/$branch")
  current_timestamp=$(date +%s)
  days_since_last_commit=$(( (current_timestamp - last_commit_timestamp) / 86400 ))

  if [[ $days_since_last_commit -ge $INACTIVE_DAYS ]]; then
    echo "待删除分支:$branch,最后更新于 $days_since_last_commit 天前"
    if [[ $DRY_RUN == false ]]; then
      git push $REMOTE_NAME --delete "$branch"
    fi
  fi
done

使用说明

  • 先调整脚本开头的配置项,确认保护分支、闲置时间符合你的需求
  • 第一次执行保持DRY_RUN=true,确认输出的待删除分支列表无误后,再改成false执行真实删除

方案2:原生Git实现(无需额外工具)

如果你无法安装GitHub CLI,可以用原生Git命令实现,逻辑如下:

#!/bin/bash
REMOTE_NAME="origin"
PROTECTED_BRANCHES=("main" "master" "develop")
INACTIVE_DAYS=30
DRY_RUN=true

git fetch $REMOTE_NAME --prune
# 获取所有PR的头哈希列表
ALL_PR_HASHES=($(git ls-remote $REMOTE_NAME 'refs/pull/*/head' | awk '{print $1}'))

# 遍历所有远程分支
for branch in $(git branch -r | grep "$REMOTE_NAME/" | sed "s/$REMOTE_NAME\///"); do
  # 跳过保护分支
  skip=0
  for protected in "${PROTECTED_BRANCHES[@]}"; do
    [[ $branch == $protected ]] && { skip=1; break; }
  done
  [[ $skip == 1 ]] && continue

  # 获取当前分支的头哈希
  branch_hash=$(git rev-parse "$REMOTE_NAME/$branch")
  # 检查该哈希是否属于未合并的PR头
  if [[ " ${ALL_PR_HASHES[*]} " =~ " $branch_hash " ]]; then
    # 额外校验该PR是否已合并到主分支
    if git merge-base --is-ancestor "$branch_hash" "$REMOTE_NAME/main"; then
      echo "分支$branch关联的PR已合并,可清理"
    else
      continue
    fi
  fi

  # 校验闲置时间
  last_commit_ts=$(git log -1 --format=%ct "$REMOTE_NAME/$branch")
  days_since=$(( ($(date +%s) - last_commit_ts) / 86400 ))
  if [[ $days_since -ge $INACTIVE_DAYS ]]; then
    echo "待删除分支:$branch,最后更新于$days_since天前"
    [[ $DRY_RUN == false ]] && git push $REMOTE_NAME --delete "$branch"
  fi
done

注意事项

  • 所有脚本执行前请先运行dry run模式确认删除列表,避免误操作
  • 建议在仓库配置保护分支规则,锁定核心分支,即使脚本逻辑出错也无法删除核心分支
  • 可将脚本配置为仓库的CI定时任务,每周自动执行一次清理

内容的提问来源于stack exchange,提问作者alextdaada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:24:04