删除分支是每天都会碰到的操作,绝大多数人只记住 -d 是安全删除、-D 是强制删除,但什么时候该用哪个,往往要到报错才知道。这篇文章我按自己处理分支的习惯,拆开讲清楚两个参数背后的检查逻辑,以及删除前、删除后需要留意的地方。
-d 和 -D 不是同一个东西的两档,而是两道不同的门
先看最核心的区别:git branch -d 用于删除已经合并到当前分支的分支,而 -D 则是强制删除,即使目标分支还没有合并也不会报错。换句话说,-d 是安全删除,它会先检查目标分支的提交是否已经存在于当前分支的历史中;-D 则跳过这个检查,直接移除分支引用。当你看到 error: The branch 'xxx' is not fully merged 的提示时,说明 -d 拒绝执行,只有改用 -D 才能强行删除。
所以在我的工作流里,-d 是第一选择,-D 是明知要丢失改动时的最后手段。如果代码已经合并到远程,并且远程分支被保留,本地分支删掉后还可以从远程重新创建;如果改动从未合并,-D 就是把那部分提交推到悬空状态。
先用 git branch --merged / --no-merged 判断合并状态
要判断一个分支是否可以用 -d 安全删除,最简单的方法是执行 git branch --merged 查看哪些分支已经合并到当前分支。输出列表中带星号的是当前分支,其余分支都可以直接用 -d 删除。反过来,git branch --no-merged 列出的分支未合并,如果直接 -d 会被拒绝。注意这个检查是相对于当前分支而言的,如果目标分支合并到了其他分支而不是当前分支,也会被判定为未合并。
实际操作时,我会先切到主分支(比如 main),然后运行:
git branch --merged
git branch --no-merged--merged 列出的分支,可以在确认当前分支状态干净后逐个删除;--no-merged 列出的分支,不要急着 -D,先打开日志看看到底有哪些提交是独有的。
删除前最后确认一次:这些提交会不会消失
日常删除分支时,优先使用 -d,只有确认该分支的改动确实不需要了,才用 -D。如果你只是想在删除前再确认一次,可以先运行 git log --oneline --not --all 查看该分支上有哪些提交不在任何其他分支中。若输出为空,说明这些提交都已经包含在其他分支里,放心用 -d;若有输出,说明这些提交会丢失,请先备份或合并。
git log --oneline --not --all 的关键点是 --not --all,这个参数过滤掉所有分支、标签和远程跟踪分支能访问到的提交,剩下的就是“只存在待删分支里”的提交。如果输出里出现一些临时提交、调试输出,那就要判断这些提交是否需要保留。需要保留的话,可以先将分支合并到当前分支,再执行 -d;确实不要了,再用 -D。
-D 之后,分支还能找回吗
-D 并不会删除工作区中的改动,它只是移除分支指针,但那些未被引用的提交会进入悬空状态。如果你刚执行完 git branch -D feature,发现其实还需要里面的代码,可以用 git reflog 找到该分支最后一次指向的 commit 哈希,然后 git branch feature 把它恢复回来。但如果仓库运行了 gc,悬空提交可能被清理,恢复就有风险,所以关键分支尽量别用 -D。
恢复的具体步骤如下:先执行 git reflog,找到类似 “feature@{0}: branch: Created from ... ” 或者 “commit: ... ” 的记录,复制那个 commit 哈希;接着执行 git branch feature
远程跟踪分支上的 -d 坑
这里要注意:一个常见的坑是:你刚从远程拉取了一个分支,然后在本地直接 git branch -d origin/feature,这会报错,因为远程跟踪分支名以 origin/ 开头,-d 会把它当作本地分支处理。正确做法是先 git checkout feature 然后在本地分支上操作,或者用 git branch -rd origin/feature 删除远程跟踪分支。另外,-d 只能删除已合并分支,如果分支上只有一次提交且刚提交完,也不要用 -D,先考虑是否要保留这次提交并合并到当前分支。
这里区分两个对象:本地分支和远程跟踪分支。git branch 默认操作的是本地分支,远程跟踪分支需要用 -r 参数管理。如果你的目的是部署后清理本地临时分支,就只删本地分支;如果你想让本地仓库忘记某个远程分支的状态,才用 -rd。删除前先用 git branch -a 看一遍完整列表,能少踩这个坑。