当前位置:   article > 正文

使用脚本批量删除远端分支_git 批量删除远程分支

git 批量删除远程分支

前言

        每月迭代结束,都不会主动去删除自己创建的分支,而仓库分支几年都没有清理,导致branchs差不多2k条。

 

思路

一、用脚本实现批量删除,无需手动执行git命令批量操作

二、支持筛选条件,如:已合并的分支、最后一次commit在三个月前、包含release字符的分支

版本一

  1. #!/bin/bash
  2. repository_name="$1"
  3. echo "您即将删除【"$repository_name"】下的分支,请先找其他人备份好,以免误删!!!!";
  4. echo " "
  5. # 过滤条件,将无需删除的分支加入到这个数组中
  6. excluded_branches=("master" "develop")
  7. # 指定要过滤的分支名称中需包含的字符(为空则不进行该过滤)
  8. excluded_filter="release/1."
  9. # 指定要删除的分支名称中需包含的字符(为空则不进行该过滤)
  10. # include_filter=""
  11. # 获取当前系统时间的秒数
  12. current_time=$(date +%s)
  13. # 计算三个月前的时间戳
  14. three_months_ago=$((current_time - 3600 * 24 * 90))
  15. # 计算两个月前的时间戳
  16. two_months_ago=$((current_time - 3600 * 24 * 60))
  17. # 计算一个月前的时间戳
  18. one_months_ago=$((current_time - 3600 * 24 * 30))
  19. # 获取所有已合并的远程分支,并进行循环处理
  20. for branch in `git branch -r --merged origin/master | grep -v HEAD`; do
  21. # 提取分支名称
  22. # simple_name=$(echo "$branch" | grep '/' | cut -d'/' -f 2);
  23. simple_name=$(echo "$branch" | sed 's#.*origin/##')
  24. # 排除不需要删除的分支
  25. excluded_flag="0";
  26. for excluded_branch in "${excluded_branches[@]}"; do
  27. if [[ "$simple_name" == "$excluded_branch" ]]; then
  28. excluded_flag="1";
  29. break
  30. fi
  31. done
  32. # 判断是否满足删除条件
  33. if [[ $excluded_flag == "0" ]]; then
  34. if [[ -n $excluded_filter ]]; then
  35. if [[ "$simple_name" == *"$excluded_filter"* ]]; then
  36. continue
  37. fi
  38. fi
  39. # if [[ -n $include_filter ]]; then
  40. # if [[ "$simple_name" != *"$include_filter"* ]]; then
  41. # continue
  42. # fi
  43. # fi
  44. # 获取分支最后提交时间
  45. branch_timestamp=$(git show --format="%at" "$branch" | head -n1)
  46. # 根据实际需要选择 三个月前 $three_months_ago 两个月$two_months_ago 一个月前$one_months_ago 当前$current_time
  47. if [[ $branch_timestamp -lt $three_months_ago ]]; then
  48. echo "正在删除分支: $simple_name"
  49. # 删除本地分支
  50. # git branch -d "$simple_name"
  51. # 删除远程分支
  52. git push origin --delete "$simple_name"
  53. echo "分支 $simple_name 删除完成"
  54. echo ""
  55. fi
  56. fi
  57. done
  58. echo "清除结束"

问题一:删除分支过后,会出现本地与远端不一致的情况,导致去删除不存在的分支(通过pull无法解决)

原因:删除分支过后,会出现本地与远端不一致的情况,导致去删除不存在的分支(通过pull无法解决)

解决方法:增加更新远端与本地引用命令

htps://blog.csdn.net/BryantLmm/article/details/85130091

Git - git-remote Documentation

版本二

增加更新远端与本地引用命令

  1. #!/bin/bash
  2. repository_name="$1"
  3. echo "您即将删除【"$repository_name"】下的分支,请先找其他人备份好,以免误删!!!!";
  4. echo " "
  5. # 过滤条件,将无需删除的分支加入到这个数组中
  6. excluded_branches=("master" "develop")
  7. # 指定要过滤的分支名称中需包含的字符(为空则不进行该过滤)
  8. excluded_filter="release/1."
  9. # 指定要删除的分支名称中需包含的字符(为空则不进行该过滤)
  10. include_filter=""
  11. # 获取当前系统时间的秒数
  12. current_time=$(date +%s)
  13. # 计算三个月前的时间戳
  14. three_months_ago=$((current_time - 3600 * 24 * 90))
  15. # 计算两个月前的时间戳
  16. two_months_ago=$((current_time - 3600 * 24 * 60))
  17. # 计算一个月前的时间戳
  18. one_months_ago=$((current_time - 3600 * 24 * 30))
  19. echo "更新本地与远端的分支引用"
  20. # 先更新分支引用,确保git branch -r拉取的分支信息,与远端仓库一致(有删除过分支会出现不一致的情况,导致不必要的遍历)
  21. git remote update origin --prune
  22. echo "更新完毕,开始批量删除目标分支"
  23. # 获取所有已合并的远程分支,并进行循环处理
  24. # for branch in `git branch -r --merged origin/master | grep -v HEAD`; do
  25. # 获取所有的远程分支,并进行循环处理
  26. for branch in `git branch -r | grep -v HEAD`; do
  27. # 提取分支名称
  28. # simple_name=$(echo "$branch" | grep '/' | cut -d'/' -f 2);
  29. simple_name=$(echo "$branch" | sed 's#.*origin/##')
  30. # 排除不需要删除的分支
  31. excluded_flag="0";
  32. for excluded_branch in "${excluded_branches[@]}"; do
  33. if [[ "$simple_name" == "$excluded_branch" ]]; then
  34. excluded_flag="1";
  35. break
  36. fi
  37. done
  38. # 判断是否满足删除条件
  39. if [[ $excluded_flag == "0" ]]; then
  40. if [[ -n $excluded_filter ]]; then
  41. if [[ "$simple_name" == *"$excluded_filter"* ]]; then
  42. continue
  43. fi
  44. fi
  45. if [[ -n $include_filter ]]; then
  46. if [[ "$simple_name" != *"$include_filter"* ]]; then
  47. continue
  48. fi
  49. fi
  50. # 获取分支最后提交时间
  51. branch_timestamp=$(git show --format="%at" "$branch" | head -n1)
  52. # 根据实际需要选择 三个月前 $three_months_ago 两个月$two_months_ago 一个月前$one_months_ago 当前$current_time
  53. if [[ $branch_timestamp -lt $three_months_ago ]]; then
  54. echo "正在删除分支: $simple_name"
  55. # 删除本地分支
  56. # git branch -d "$simple_name"
  57. # 删除远程分支
  58. git push origin --delete "$simple_name"
  59. echo "分支 $simple_name 删除完成"
  60. echo ""
  61. fi
  62. fi
  63. done
  64. echo "清除结束"

最终版

加上询问交互

  • 安装inquirer.js

inquirer中文文档|inquirer js中文教程|解析 | npm中文文档

node执行脚本传参,支持传空的写法

用""包裹参数,不能只用空格分隔

node传入脚本,shell支持动态变量赋值

node用esec执行脚本,不能实时输出,会等脚本执行完毕一次性输出打印内容

nodejs 如何执行 shell 命令,并把结果实时回显输出?

Child process | Node.js v21.1.0 Documentation

解决方案:

用spawn替换exec

动态传入拉取分支规则

问题:这种写法会导致打印输出所有分支到控制台

解决:

 代码如下:

  1. const inquirer = require('inquirer');
  2. const { spawn } = require('child_process');
  3. const format = {
  4. three_months_ago: '90天前',
  5. two_months_ago: '60天前',
  6. one_months_ago: '30天前',
  7. current_time: '当前',
  8. branch_all: '所有分支',
  9. branch_merged: '已合并',
  10. branch_no_merged: '未合并',
  11. }
  12. const label = {
  13. name: '当前项目是:',
  14. excluded_filter: '指定要过滤的分支名称中需包含的字符:',
  15. include_filter: '指定要删除的分支名称中需包含的字符:',
  16. date_range: '过滤日期范围:',
  17. branch_rule: '获取远程分支范围:',
  18. }
  19. const question = [{
  20. type: 'input',
  21. message: '当前项目是:',
  22. name: 'name',
  23. default: 'ircloud-ydp-web'
  24. },
  25. {
  26. type: 'input',
  27. message: '指定要过滤的分支名称中需包含的字符(为空则不进行该过滤):',
  28. name: 'excluded_filter',
  29. default: 'release/1.'
  30. },
  31. {
  32. type: 'input',
  33. message: '指定要删除的分支名称中需包含的字符(为空则不进行该过滤):',
  34. name: 'include_filter',
  35. default: ''
  36. },
  37. {
  38. type: 'list',
  39. message: '过滤日期范围:',
  40. name: 'date_range',
  41. choices: ['three_months_ago', 'two_months_ago', 'one_months_ago', 'current_time'],
  42. default: 'three_months_ago',
  43. },
  44. {
  45. type: 'list',
  46. message: '获取远程分支范围(全部、已合并、未合并):',
  47. name: 'branch_rule',
  48. choices: ['branch_all', 'branch_merged', 'branch_no_merged'],
  49. default: 'branch_all',
  50. }]
  51. let answer = {}
  52. function getParams () {
  53. return inquirer.prompt(question).then(res => {
  54. console.log(res)
  55. answer = {...res}
  56. })
  57. }
  58. function confirmAgain () {
  59. const str = Object.keys(answer).reduce((prev, curr) => {
  60. if(['date_range', 'branch_rule'].includes(curr)) {
  61. prev += `${label[curr]} ${format[answer[curr]]}; `;
  62. }else{
  63. prev += `${label[curr]} ${answer[curr]}; `;
  64. }
  65. return prev;
  66. }, '')
  67. return inquirer.prompt([{
  68. type: 'list',
  69. message: `${str},确定吗?`,
  70. name: 'answer',
  71. choices: ['yes', 'no'],
  72. default: 'yes'
  73. }]).then(res => {
  74. if (res.answer === 'yes') {
  75. // let params = Object.values(res).reduce((prev, curr) => {
  76. // prev += `"${curr}" `;
  77. // return prev
  78. // }, '')
  79. // console.log(`bash scripts/delBranch.sh ${params}`);
  80. // exec(`bash scripts/delBranch.sh ${params}`,(error, stdout, stderr) => {
  81. // console.log(stdout);
  82. // console.log(stderr);
  83. // if (error !== null) {
  84. // console.log(`exec error: ${error}`);
  85. // }
  86. // })
  87. console.log('参数获取完毕,开始执行删除脚本');
  88. let paramsArr = Object.values(answer);
  89. const childProcess = spawn('sh', [`scripts/delBranch.sh`, ...paramsArr]);
  90. childProcess.stdout.on('data', (data) => {
  91. console.log(`脚本执行输出:${data}`);
  92. });
  93. childProcess.stderr.on('data', (data) => {
  94. console.error(`脚本错误信息:${data}`)
  95. })
  96. } else {
  97. console.log('终止执行');
  98. }
  99. })
  100. }
  101. async function main() {
  102. await getParams();
  103. await confirmAgain();
  104. }
  105. main();
  1. #!/bin/bash
  2. repository_name="$1"
  3. echo "您即将删除【"$repository_name"】下的分支,请先找其他人备份好,以免误删!!!!";
  4. echo " "
  5. # 过滤条件,将无需删除的分支加入到这个数组中
  6. excluded_branches=("master" "develop")
  7. # 指定要过滤的分支名称中需包含的字符(为空则不进行该过滤)
  8. # excluded_filter="release/1."
  9. excluded_filter=$(echo ${2})
  10. # 指定要删除的分支名称中需包含的字符(为空则不进行该过滤)
  11. include_filter=$(echo ${3})
  12. # 获取当前系统时间的秒数
  13. current_time=$(date +%s)
  14. # 计算三个月前的时间戳
  15. three_months_ago=$((current_time - 3600 * 24 * 90))
  16. # 计算两个月前的时间戳
  17. two_months_ago=$((current_time - 3600 * 24 * 60))
  18. # 计算一个月前的时间戳
  19. one_months_ago=$((current_time - 3600 * 24 * 30))
  20. time_range=$(eval echo '$'${4})
  21. echo "更新本地与远端的分支引用"
  22. # 先更新分支引用,确保git branch -r拉取的分支信息,与远端仓库一致(有删除过分支会出现不一致的情况,导致不必要的遍历)
  23. git remote update origin --prune
  24. echo "更新完毕,开始批量删除目标分支"
  25. branch_all="";
  26. branch_merged="--merged origin/master";
  27. branch_no_merged="--no-merged origin/master";
  28. get_branch_rule=$(eval echo '$'${5})
  29. # 获取(所有/已合并/未合并)的远程分支,并进行循环处理
  30. for branch in `git branch -r ${get_branch_rule} | grep -v HEAD` ; do
  31. # 提取分支名称
  32. # simple_name=$(echo "$branch" | grep '/' | cut -d'/' -f 2);
  33. simple_name=$(echo "$branch" | sed 's#.*origin/##')
  34. # 排除不需要删除的分支
  35. excluded_flag="0";
  36. for excluded_branch in "${excluded_branches[@]}"; do
  37. if [[ "$simple_name" == "$excluded_branch" ]]; then
  38. excluded_flag="1";
  39. break
  40. fi
  41. done
  42. # 判断是否满足删除条件
  43. if [[ $excluded_flag == "0" ]]; then
  44. if [[ -n $excluded_filter ]]; then
  45. if [[ "$simple_name" == *"$excluded_filter"* ]]; then
  46. continue
  47. fi
  48. fi
  49. if [[ -n $include_filter ]]; then
  50. if [[ "$simple_name" != *"$include_filter"* ]]; then
  51. continue
  52. fi
  53. fi
  54. # 获取分支最后提交时间
  55. branch_timestamp=$(git show --format="%at" "$branch" | head -n1)
  56. # 根据实际需要选择 三个月前 $three_months_ago 两个月$two_months_ago 一个月前$one_months_ago 当前$current_time
  57. if [[ $branch_timestamp -lt $time_range ]]; then
  58. echo "正在删除分支: $simple_name"
  59. # 删除本地分支
  60. # git branch -d "$simple_name"
  61. # 删除远程分支
  62. git push origin --delete "$simple_name"
  63. echo "分支 $simple_name 删除完成"
  64. echo ""
  65. fi
  66. fi
  67. done
  68. echo "清除结束"

package.json中加上执行命令

"delete-node": "node scripts/inquirerDelBranch.js"

结束

当时一键点击是最省时的

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/437854
推荐阅读
相关标签
  

闽ICP备14008679号