记一次git清理历史危机

缘由

近一段时间在线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也不会执行,免得所有的引用都没了

  1. 立即停止操作:恢复前不要执行 git gc 或清理操作,以免永久丢失数据。
  2. 备份当前状态:恢复前先备份当前 .git 目录。
  3. 使用更安全的工具:未来推荐使用 git filter-repo 替代 git filter-branch(官方已弃用)

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Scroll to Top