缘由
近一段时间在线CICD执行困难,经常会失败。咨询CI专家之后,发现是因为git仓库已经近1个GB,整个workspace碎片文件太多,空间占用太大,咨询CI专家如何清理之后,专家给出了以下的清理命令,但自己没有弄清这条命令具体的作用,直接就以整个项目目录为基进行执行,结果酸爽,所有的分支,没有的提交日志全清空。
git filter-branch --force --index-filter "git rm -r --cached --ignoreunmatch ./" --prune-empty --tag-name-filter cat -- --all
那为什么所有的分支和提交日志都会被清理呢,这条命令的作用是什么呢?分析分析:
- git filter-branch是用来重写历史记录的,这里的参数是强制模式
- index-filter用了git rm -r –cached –ignore-unmatch ./,这会删除所有文件的历史记录
- prune-empty会移除空的提交,tag-name-filter cat可能保留标签
- 最后指定了–all,所以所有分支和标签都被处理了
恢复之路
查了git相关的文档,在git中,执行filter-branch之后,原来的引用会被保存在refs/original/目录下。
我检查.git/refs/original/是否存在,里面可能保存了原来的分支和标签,万幸在我的.git目录中,这个文件是存在的,那接着就可以使用以下的命令来恢复了。
1、检查是否存在备份引用
git show-ref | grep refs/original/
2、恢复分支
git for-each-ref --format="%(refname)" refs/original/ | while read ref; do
git update-ref "${ref#refs/original/}" "$ref"
git update-ref -d "$ref"
done
用例
以下为我的恢复实例

结果,分支都回来了,万幸,节省了一周的工作量

建议
出了问题之后,.git千万不要再动了,git gc也不会执行,免得所有的引用都没了
- 立即停止操作:恢复前不要执行
git gc
或清理操作,以免永久丢失数据。 - 备份当前状态:恢复前先备份当前
.git
目录。 - 使用更安全的工具:未来推荐使用
git filter-repo
替代git filter-branch
(官方已弃用)