CLI AI

删除 git 中所有已合并的本地分支

2026-07-02

git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -d 会删除所有已经合并到 main 的本地分支,main 和 develop 除外。它不会动 squash merge 合并过的分支:git 从来不会把它们的提交记为已合并,所以 --merged 永远看不到它们——要找它们,得用 git branch -vv 查看 gone 标记。

1. 先看看哪些算作已合并

clai
$ clai 显示已合并到 main 的分支→ git branch --merged main  feature-merged* main

这只是一个只读列表。当前分支会标上星号,不能删除——也不需要删除。

2. 删除它们,但保护主分支

clai
$ clai 删除已合并到 main 的本地分支,main 和 develop 除外→ git branch --merged main | grep -vE '^\*|main|develop' | xargs -r git branch -dDeleted branch feature-merged (was fb52fec).

-d 是安全的:git 会拒绝删除包含未合并提交的分支。grep -vE 过滤是必须的,否则 main 自己也会出现在列表里。-r 能防止列表为空时 xargs 还去执行。

3. 确认没有误删重要分支

clai
$ clai 显示剩下的分支→ git branch  feature-open* main

feature-open 还有未合并的提交,所以原样保留。这正好验证了过滤条件是对的。

4. 陷阱:squash merge 让 --merged 看不到

clai
$ clai 显示 upstream 在服务器上已被删除的分支→ git fetch --prune && git branch -vv | grep '\[.*: gone\]'

这是最关键的部分。squash merge 不会把分支的提交原样放进 main 的历史,所以 --merged 永远看不到它——它会一直留在你的机器上。但它在服务器上的 upstream 会在 pull request 合并后被删除,git branch -vv 会把这个分支标记为 gone。这才是可靠的信号。

5. 删除 upstream 已消失的分支

clai
$ clai 删除源分支已在服务器上删除的本地分支→ git fetch --prune && git branch --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D⚠ CAUTION — this is -D, not -d: it also deletes unmerged branches

用 -D 正是因为 git 不认为 squash 合并过的分支已经合并,-d 会被拒绝。代价是:运行这条命令之前,先看清楚上一条命令给出的列表。

6. 清理过期的远程引用

clai
$ clai 清除服务器上已不存在的分支引用→ git remote prune origin

这只会删除本地的 origin/* 引用,不会动到你的分支。当自动补全一直提示半年前就关闭的分支时,这个很有用。

常见陷阱

  • -d 和 -D 的风险等级不同。 小写只删除已合并的,大写什么都删。squash 合并的分支需要用大写,所以先列出来,再删除。
  • --merged 不带参数时,是以当前分支为准计算的。 站在 feature 分支上会得到完全不同的列表。要明确指定基准:--merged main。
  • 删除本地分支不会删除服务器上的分支。 那需要 git push origin --delete <名称>。反过来也一样:服务器上删除不会移除你的本地副本。

相关问题

怎么找回不小心删除的分支? git reflog 会显示它最后的提交,然后用 git branch <名称> <哈希> 就能恢复。只要垃圾回收还没运行就有效。

为什么分支删不掉? 要么你正站在这个分支上——切到 main 就行,要么它有未合并的提交,-d 是在保护你不丢失它们。

怎么看分支最后一次更新是什么时候? git branch --sort=-committerdate -v 会按更新时间排序——方便找出被遗忘的分支。

相关阅读

CliAI 会把上面这些说法转换成准确的命令,并在执行前展示出来——用到 -D 的那一步会带上 CAUTION 标签,而不是悄悄运行。一行命令安装。