Git可能并不安全的安全删除分支


删除分支是 git 使用中再正常不过的操作了,不论是删除远程还是本地分支。

什么,你不知道怎么删除?那这里就贴一下好了

1
2
3
4
5
6
7
8
# 安全删除本地分支(未合并到当前分支的不予删除)
git branch -d 分支名1 分支名2
# 强制删除本地分支
git branch -D 分支名1 分支名2

# 删除远程分支
git push -d 远程别名 分支名
git push 远程别名 :分支名

实际工作中为了互相不干扰工作,经常需要新建分支开发具体相关功能,开发完毕后再合并到主分支。

如果你是和我一样的人群,总是忘记懒得删除合并过的分支的话,就往往在一段时间后不得不面对一个问题:过多本地无用分支堆积

你也不想在查看分支的时候变成下面这种结果吧

1
2
3
4
5
6
7
8
9
10
11
12
13
git branch
master
dev
dev-post-1111
bugfix-post-1110
dev-access-1108
dev-assets-1031
dev-check-1023
dev-detail-1109
dev-newWeb2.0
dev-plan-1031
dev_accessFix1030
* dev_ejj_1031

没办法,只能手动删除掉这些无用分支了。为了防止删除未合并的分支,我们可以很容易地想到使用如下命令删除:

1
git branch -d 分支名1 分支名2

使用 -d 参数时,遇到未合并到当前分支的的分支时,将会报错并阻止删除,可以起到一层过滤作用:删掉已合并的,保留未合并的。

但似乎事与愿违,删除后,我收到了下面的结果,绝大多数未合并分支都弹出 error 报错并阻止了删除,但唯独有两个未合并分支丢出 warning 后依旧删除了事

删除结果

问题复现

经过排查,这两个分支均为我从远程拉取的分支,即下面的操作(后续均以 origin 远程别名与 dev 分支名为例):

1
2
git fetch origin dev
git checkout dev

而后我修改了分支的内容并推送到了远程相对应的分支,使得本地与远程分支内容保持一致

1
git push origin dev

此时再使用 -d 进行删除,便会复现上面的 “阻止删除但没有完全阻止” 的情况:git 仅会给予警告,但仍会删掉本地的分支快照。

问题解释

这样所创建的分支本质上是一个远程跟踪分支的副本,其与 origin/dev 相关联。当切换到此类分支时,git 将会给予提示

1
Your branch is up to date with 'origin/dev'.

删除此类本地分支并不会影响远程跟踪分支 origin/dev 的存在,即使删除后也依旧可以通过简单的切换分支来恢复

1
git checkout dev

但若在删除此类本地分支后,再删除远程分支,则可以在安全删除的操作下永远失去改动数据。

1
2
git branch -d dev
git push -d origin dev

可能这就是 git 会给出 warning 提示的原因。

而通过下面两种操作创建的真实的本地分支,未与远程跟踪分支相关联,则 -d 依然能够起到安全删除的作用。

1
2
git branch dev
git checkout -b dev

尝试未合并时安全删除:

1
git branch -d dev

删除失败,得到错误提示信息

1
2
error: The branch 'dev2' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dev2'.