git 高级命令模式典型应用--“同步云端 + 清理垃圾分支”的一键命令
本文介绍了一种通过配置Git别名(新建命令)一键清理本地冗余分支的方法。通过添加名为<sweep>的自定义命令,可自动完成三个步骤:
1)同步远端分支和标签状态,清理已删除的远端跟踪分支;
2)删除已合并到当前分支的本地分支(保留主干分支);
3)清理上游已被删除的本地分支。
该方法通过gitconfig全局配置,使用安全删除选项(-d)确保未合并分支不会被误删,帮助开发者轻松保持本地仓库的整洁。最终只需执行 <git sweep> 即可实现云端与本地分支状态的同步清理。
团队协作中,由于不断的拉取新分支,和并到父分支,并删除分支的操作,会导致本地仓库看到的分支很冗杂,并保留了好多云端已经删除的分支;
本文核心目的是保持本地仓库的清爽优雅;
本质上要做到端云同步,而要做这个同步的动作指令又不是很优雅;
最终我们通过修改git配置的方式,新增一个sweep命令,一键优雅解决;详细方法参考:
三. 清扫命令配置
一、同步最新云端仓(分支 & tag 状态)
1. 拉取远端最新分支 / tag,并顺便清理远端已删分支
git fetch origin --prune --tags含义:
git fetch origin:从远端 origin 拉取最新提交和分支信息--prune:把本地那些已经在远端删除的origin/xxx跟踪分支清理掉--tags:顺便更新远端的 tag
小建议:可以把
fetch.prune设成默认,省心:
git config --global fetch.prune true
git config --global remote.origin.prune true2. 把关键分支更新到最新(比如 master / release)
更新 master 分支
git switch master
git pull origin master # 或 git pull --ff-only origin master更新 release 分支(如果有)
git switch release
git pull origin release # 或 git pull --ff-only origin release
--ff-only:只允许快进更新,如果有分叉会拒绝,比较安全。
不想管那么细,直接git pull origin 分支名也可以。
二、清理本地不用的分支
目标:
删除已经合入当前主干的本地分支
删除远端已经删掉的本地分支
0. 先回到安全分支(比如 master)
git switch master # 或 main/release,看你们用哪个1. 删除“已经合入”的本地分支(安全)
git branch --merged \ | egrep -v '^\*|master|main|release|develop' \ | xargs -r git branch -d含义:
git branch --merged:列出已经合入当前分支的本地分支egrep -v ...:排除当前分支(前面有*)和你想保留的主干分支git branch -d:只删除已合入的分支,没合入会报错、不会删(很安全)
你可以按自己习惯改排除列表,比如只想保留
master和release:
egrep -v '^\*|master|release'
2. 删除“上游已经没了(gone)”的本地分支
有些本地分支的上游远端分支已经被删除了(比如 MR 合并后远端删了 origin/feature_x),
但本地的 feature_x 还在,这也可以清理掉:
git for-each-ref --format='%(refname:short) %(upstream:track)' refs/heads \ | awk '$2=="[gone]" {print $1}' \ | xargs -r git branch -d
# 或者
git fetch origin --prune --tags && git branch -vv | awk '/: gone]/{print $1}' | xargs -r git branch -d含义:
列出所有本地分支和它们的上游状态
过滤出上游是
[gone]的分支对这些分支执行
git branch -d删除
如果你确认这些分支没合入、但就是想强制删掉,可以把最后的
-d改成-D(⚠️危险,慎用)。
三、做成一个“清扫命令”别名配置,并逐一解释
可以弄一个 git 别名,一条命令完成“同步 + 清理”,例如:
可以考虑使用git config --global alias.sweep '!...' #'!...' 就是下面=后面内容; 这里我更建议去配置文件中手改;
vi ~/.gitconfig
在配置文件中增加如下内容:
[alias]sweep = !git fetch origin --prune --tags && git branch --merged | egrep -v "^\*|master|main|release|develop" | xargs -r git branch -d && git for-each-ref --format="%(refname:short) %(upstream:track)" refs/heads | awk '"'"'$2=="[gone]" {print $1}'"'"' | xargs -r git branch -d我这里的筛选规则,是符合我自己的分支命名规范的,你们自己斟酌; 可以考虑把第二行去掉也是可以;
vi ~/.gitconfig
在配置文件中增加如下内容:
[alias]sweep = !git fetch origin --prune --tags && git branch -vv | awk '/: gone]/{print $1}' | xargs -r git branch -d注意这里为了安全起见, 使用了git branch -d [如果没有merge过就删除的分支,会有提示删除失败, 如果激进点可以考虑 换成 git branch -D ]
之后只要:
git sweep就会自动:
同步远端分支/tag,并 prune
删掉已经合入的本地分支
删掉上游已经 gone 的本地分支
之后 只要到git仓库下执行这个命令: git sweep 即可;
效果相当于执行一串“同步 + 清理分支”的脚本。
下面我们把这串东西拆成三个步骤来讲,这样更清晰。
1、alias.sweep 自身是干嘛的?
关键字解释:
git config --global alias.sweep '!...'
git config:配置 Git 选项--global:作用于你当前用户的所有仓库(写进~/.gitconfig)alias.sweep:定义一个叫sweep的 别名命令'!...':!的含义:告诉 Git 这个别名后面跟的是一条 shell 命令,而不是简单的 Git 子命令组合...是真正要执行的一长串 shell 命令
之后你执行:
git sweep
Git 会当成:
git fetch origin --prune --tags && ...
也就是说,sweep 就是你自定义的一个 Git 子命令名,和 git status、git log 一样用。
2、第一段:同步远端 & 清理远端已删分支
git fetch origin --prune --tags
关键字解释:
git fetch origin
从远端 origin 拉取最新的提交和分支信息(不会修改当前分支内容,只更新远端跟踪分支origin/xxx)。--prune
意思是:“把本地那些已经在远端不存在的远端跟踪分支删掉”。
比如远端删了
origin/feature_x,你本地还残留这个远端引用,这个参数会顺便清掉这些“僵尸引用”。--tags
顺便把远端的 tag 信息也同步下来(比如新打的v1.0.22、v1.0.22-rc3)。
💡 作用总结:
同步云端状态(分支 & tag),并清理远端已删除的跟踪分支。
2、第二段:删除“已经合入当前分支”的本地分支
关键字解释
git branch --merged | egrep -v '^\*|master|main|release|develop' | xargs -r git branch -d
1. git branch --merged
列出 所有已经合入当前分支 的本地分支。
当前分支前面会有一个
*,例如:* releasefeature/user_profile
bug/12345_login_crash
这里的 feature/user_profile 等,就是已经合并进当前分支(比如 release)的分支,可以安全删除。
2. egrep -v '^\*|master|main|release|develop'
这是在过滤分支列表,避免把重要分支删掉。
egrep:扩展正则匹配,更方便写|这种“或”。-v:取反,保留不匹配模式的行。正则
'^\*|master|main|release|develop'含义:^\*:以*开头的行(当前分支),不能删master:主分支main:有些项目用 main 做主分支,兼容一下release:发布分支develop:有些团队有 develop 分支
也就是说:
把当前分支 + 若干主干分支 排除掉,只保留下那些“可以考虑删”的普通临时分支。
你可以根据自己仓库情况调整,比如你只用 master / release:
egrep -v '^\*|master|release'
3. xargs -r git branch -d
关键字解释
xargs:把前面管道传进来的每一行,当作参数传给后面的命令。-r:如果没有输入,就什么都不做(避免空输入时报错)。git branch -d <branch>:删除本地分支,前提是该分支已经完全合并到当前分支,否则会拒绝删除并报错。
安全点在这里:
使用的是
-d,不是-D:-d= 安全删除(没合入就不删)-D= 强制删除(不管有没有合入)
这一整段的意思就是:
删除所有 已经合入当前分支 的本地分支,
但保留当前分支、master、main、release、develop。
4、第三段:删除“上游已经消失”的本地分支
关键字解释
git branch -vv | awk '/: gone]/{print $1}' | xargs -r git branch -d这段是专门清理这样一种分支:
本地还有分支
feature_x,
但远端的origin/feature_x已经被删除(比如 MR 合并后服务端自动删了),
这种“上游 gone 的分支”也可以顺手清掉。
通过git branch -vv 展示出每个分支详情, 当然是在git fetch origin --prune --tags执行之后才能更新到云端已删除的分支;
如origin/feature_x云端删除
则本地看到 个数如下的提示信息:
feature_x commitid [origin/feature_x: gone] 描述信息...
2. awk '/: gone]/{print $1}'
用 文本匹配 的方式找出整行里包含
: gone]的经过这步,最后得到的就是:然后打印这一行的$1 作为分支名;
所有 上游状态为 gone 的本地分支名。
3. xargs -r git branch -d
跟上面一样:
-r:没有输入时不执行;git branch -d name:安全删除这些分支(如果没合入还会拒绝删除)。
📌 这段的作用:
删除那些“远端已经删了、但本地还留着”的分支(并且已合入当前分支)。
5、整体效果总结
git sweep 做了 3 件事:
同步远端仓库状态
分支、tag 都更新
把远端已经删掉的
origin/xxx引用 prune 掉
删除所有已经合入当前分支的本地分支 [可选]
不动
master/main/release/develop和当前分支使用安全删除
-d,没合入不会删
删除上游已 gone 的本地分支
比如远端已删
origin/feature_x,本地还在,就一起清理一样是安全删除
你可以理解为:
“同步云端 + 清理垃圾分支”的一键命令。
