批量删除分支

批量清理本地与远端分支

在日常开发中,我们频繁创建 Git 分支来进行开发和调试,但时间一长,仓库里可能堆满了废弃的分支,影响查找和管理。

手动删除分支不仅繁琐,还容易误删重要分支。 为此,我自定义了 dlb(Delete Local Branch)、drb(Delete Remote Branch)和 dab(Delete All Branch)三个命令,提供交互式选择和多选删除功能,可以一目了然地管理分支,避免混乱,提高效率。

介绍

dlb - 删除本地分支

功能

  • 删除符合指定前缀的本地分支

  • 排除 masterdevelop 等主干分支,避免误删

  • 提供可选交互模式,让用户手动选择要删除的分支

适用场景

  • 开发完某个功能或修复后,需要删除临时分支

  • 需要批量清理过时的本地分支

drb - 删除远端分支

功能

  • 删除符合指定前缀的远端分支

  • git fetch -p 更新远端分支列表,确保数据最新

  • 允许用户从列表中选择要删除的分支

适用场景

  • 远端分支合并后仍然存在,需要手动清理

  • 避免远端仓库积累过多无用分支,影响代码管理

dab - 删除本地和远程分支

功能

  • 删除符合指定前缀的本地和远程分支

  • git fetch -p 更新远端分支列表,确保数据最新

  • 允许用户从列表中选择要删除的分支

适用场景

  • 本地和远程分支合并后仍然存在,需要手动清理。
  • 避免本地和远程仓库积累过多无用分支,影响代码管理。
  • 需要同时清理本地和远程仓库中特定前缀的分支。

配置方法

dlbdrb 代码添加到 ~/.zshrc 文件中,并执行以下命令使其生效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# 删除本地分支(排除 master 和 develop)
dlb() {
# 检查是否在 Git 仓库内
if [[ ! -d .git ]]; then
echo "❌ 错误:当前目录不是 Git 仓库"
return 1
fi

local prefix="$1"
if [[ -z "$prefix" ]]; then
echo "用法: dlb <分支前缀>"
return 1
fi

# 使用 git for-each-ref 获取分支
local branches=($(git for-each-ref --format='%(refname:short)' refs/heads | grep "$prefix" | grep -v -E "^(master|develop)$"))

if [[ ${#branches[@]} -eq 0 ]]; then
echo "✅ 没有匹配的本地分支"
return 0
fi

echo "即将删除以下本地分支:"

# 使用关联数组存储序号和分支名称的映射关系
declare -A branch_map
local i=1
for branch in "${branches[@]}"; do
branch_map[$i]="$branch"
echo "$i) $branch"
((i++))
done

print -n "选择要删除的分支编号(多个用空格分开): "
read -r input

local selected_indexes=(${(s. .)input})

if [[ ${#selected_indexes[@]} -eq 0 ]]; then
echo "❌ 没有选择任何分支"
return 1
fi

# 遍历用户选择的序号
for index in "${selected_indexes[@]}"; do
if [[ "$index" =~ ^[0-9]+$ ]]; then
# 使用关联数组直接查找分支名称
local branch="${branch_map[$index]}"

if [[ -n "$branch" ]]; then # 检查是否找到了对应的分支
echo "✅ 正在删除分支 $branch..."
if git branch -D "$branch"; then
echo "✅ 分支 $branch 删除成功。"
else
echo "❌ 删除分支 $branch 失败,可能存在其他问题。"
fi
else
echo "❌ 无效的分支选择:$index (超出范围或不存在)"
fi
else
echo "❌ 输入无效:$index 不是有效的分支编号"
fi
done
}


# 删除远端分支
drb() {
# 检查是否在 Git 仓库内
if [[ ! -d .git ]]; then
echo "❌ 错误:当前目录不是 Git 仓库"
return 1
fi

local prefix="$1"

if [[ -z "$prefix" ]]; then
echo "用法: drb <分支前缀>"
return 1
fi

# 更新本地远端分支信息
echo "正在更新本地远端分支信息..."
if ! git fetch -p; then
echo "❌ 更新本地远端分支信息失败,请检查网络连接或 Git 仓库状态。"
return 1
fi
echo "✅ 本地远端分支信息更新完成。"

# 获取远端分支列表
local remote_branches=($(git for-each-ref --format='%(refname:short)' refs/remotes/origin | grep "$prefix"))

if [[ ${#remote_branches[@]} -eq 0 ]]; then
echo "✅ 没有匹配的远端分支"
return 0
fi

echo "即将删除以下远端分支:"

# 显示分支列表
declare -A remote_branch_map
local i=1
for branch in "${remote_branches[@]}"; do
local display_branch=$(echo "$branch" | sed 's/^origin\///')
remote_branch_map[$i]="$branch"
echo "$i) $display_branch"
((i++))
done

print -n "选择要删除的远端分支编号(多个用空格分开,输入 q 退出): "
read -r input

if [[ "$input" == "q" ]]; then
echo "操作已取消。"
return 0
fi

local selected_indexes=(${(s. .)input})

if [[ ${#selected_indexes[@]} -eq 0 ]]; then
echo "❌ 没有选择任何分支"
return 1
fi

# 遍历用户选择的序号并删除远端分支
for index in "${selected_indexes[@]}"; do
if [[ "$index" =~ ^[0-9]+$ ]]; then
local full_branch="${remote_branch_map[$index]}"
if [[ -n "$full_branch" ]]; then
local branch=$(echo "$full_branch" | sed 's/^origin\///')

# 判断是否为 master 或 develop 分支
if [[ "$branch" == "master" || "$branch" == "develop" ]]; then
echo "❌ 禁止删除 '$branch' 分支。master 和 develop 分支是受保护分支。"
continue # 跳过该分支,继续处理下一个分支
fi

echo "✅ 正在删除远端分支 '$branch'..."
if git push origin --delete "$branch"; then
echo "✅ 远端分支 '$branch' 删除成功。"
else
echo "❌ 删除远端分支 '$branch' 失败,可能存在其他问题。 请通过 Web 界面或检查相关配置删除"
fi
else
echo "❌ 无效的分支选择:$index (超出范围或不存在)"
fi
else
echo "❌ 输入无效:$index 不是有效的分支编号"
fi
done
return 0 # 删除完所有选择的分支后,直接退出
}

# 删除本地和远端分支
dab() {
# 检查是否在 Git 仓库内
if [[ ! -d .git ]]; then
echo "❌ 错误:当前目录不是 Git 仓库"
return 1
fi

local prefix="$1"
if [[ -z "$prefix" ]]; then
echo "用法: dab <分支前缀>"
return 1
fi

# 1. 更新本地远端分支信息
echo "正在更新本地远端分支信息..."
if ! git fetch -p; then
echo "❌ 更新本地远端分支信息失败,请检查网络连接或 Git 仓库状态。"
return 1
fi
echo "✅ 本地远端分支信息更新完成。"

# 2. 获取所有匹配的分支(包括本地和远程),去除重复的分支名称
local branches=()
local branch
# 获取所有本地和远程分支,去重,且排除 master 和 develop
git branch -a | grep "$prefix" | grep -v -E "^(master|develop)$" | sed 's/\* //' | while read branch; do
if [[ "$branch" =~ remotes/origin/ ]]; then
# 如果是远程分支,去掉 remotes/origin/ 前缀
branch="${branch#remotes/origin/}"
fi
# 将处理后的分支添加到列表中(去重)
branches+=("$branch")
done

# 去重:移除重复的分支
branches=($(echo "${branches[@]}" | tr ' ' '\n' | sort | uniq | tr '\n' ' '))

# 3. 显示分支列表并让用户选择
echo "即将删除以下本地和远程分支:"

declare -A branch_map
local i=1
for branch in "${branches[@]}"; do
branch_map[$i]="$branch"
echo "$i) $branch"
((i++))
done

echo -n "选择要删除的分支编号(多个用空格分开): "
# 使用 read 来获取用户输入
read -r input

# 将输入分割为数组
selected_indexes=(${(s. .)input})

if [[ ${#selected_indexes[@]} -eq 0 ]]; then
echo "❌ 没有选择任何分支"
return 1
fi

# 4. 循环删除选择的分支
for index in "${selected_indexes[@]}"; do
# 将索引转换为数字类型
local num_index=$((index))

# 检查索引是否超出范围
if [[ "$num_index" -lt 1 || "$num_index" -gt ${#branches[@]} ]]; then
echo "❌ 输入的编号 $index 超出范围,请重新输入。"
continue # 跳过本次循环
fi

local branch="${branch_map[$num_index]}"
echo "✅ 正在删除分支 $branch..."

# 1. 尝试删除本地分支
if git branch -D "$branch"; then
echo "✅ 本地分支 $branch 删除成功。"
else
echo "❌ 删除本地分支 $branch 失败。"
fi

# 2. 尝试删除远程分支
if git push origin --delete "$branch" 2>&1 | tee /dev/tty | grep -q 'error'; then
echo "❌ 远程分支 $branch 删除失败。"
else
echo "✅ 远程分支 $branch 删除成功。"
fi
done

# 5. 更新本地分支信息
echo "正在更新本地远端分支信息..."
if ! git fetch -p; then
echo "❌ 更新本地远端分支信息失败,请检查网络连接或 Git 仓库状态。"
return 1
fi
echo "✅ 本地远端分支信息更新完成。"
}

执行source ~/.zshrc重载配置

使用示例

dlb

1
dlb feature/

执行后,它会列出所有以 feature/ 开头的本地分支(排除 master 和 develop),让你选择要删除的分支。

示例输出:

1
2
3
4
5
6
7
8
9
10
11
12

即将删除以下本地分支:
1) feature/login
2) feature/dashboard
3) feature/refactor

选择要删除的分支编号(多个用空格分开): 1 3
✅ 正在删除 feature/login...
✅ 删除成功
✅ 正在删除 feature/refactor...
✅ 删除成功

drb

1
drb bugfix/

执行后,它会列出所有以 bugfix/ 开头的远端分支,并让你选择要删除的分支。

示例输出:

1
2
3
4
5
6
7
8
9
10
正在更新本地远端分支信息...
✅ 本地远端分支信息更新完成。

即将删除以下远端分支:
1) bugfix/api-error
2) bugfix/ui-glitch

选择要删除的远端分支编号(多个用空格分开,输入 q 退出): 2
✅ 正在删除远端分支 bugfix/ui-glitch...
✅ 远端分支 'bugfix/ui-glitch' 删除成功。

dab

1
dab feature/

和上方输入输入相同,不做赘述


批量删除分支
https://ortonzhang.github.io/2025/02/13/gitCmdFn/
作者
orton
发布于
2025年2月13日
许可协议