要从所有git历史记录中删除大量不需要的文件,您可以使用filter-branch
重写每个提交的索引(repo中的文件列表),以便永远不会添加该文件。
git filter-branch --index-filter "git rm --cached --ignore-unmatch path/to/offending_file.wav" --tag-name-filter cat -- --all
但是,如果我想保留文件但要使其小得多(例如想象一个图标是否被意外存储为巨大的图像)。我试过这种方法:
首先将替换文件添加到git的数据库
HASH=`git hash-object -w /tmp/replacement.png`
另请注意我们要替换的文件
FILE="path/to/icon.png"
现在按如下方式过滤索引:首先检查此提交中是否存在该文件:
git cat-file -e :"$FILE"
如果有,请将其从索引中删除:
git rm --cached "$FILE"
最后用相同的文件名添加对替换的引用。
git update-index --add --cacheinfo "100644,$HASH,$FILE"
全部放在一起:
git filter-branch --index-filter "if git cat-file -e :$FILE ; then git rm --cached $FILE ; git update-index --add --cacheinfo 100644,$HASH,$FILE ; fi" --tag-name-filter cat -- --all
这似乎有效,并且不会打印任何太可怕的错误。但是,无论我尝试了多少git gc
和prune命令,原始blob仍然存在于存储库中。即使我将回购克隆克隆到新的地方,它仍然存在。
我怀疑这是因为远程引用,original
创建的filter-branch
引用仍然指向旧树,因此原始文件仍然被引用。
我确实尝试用这样的黑客删除它们:
for REF in `git show-ref | cut -c 42- | grep original` ; do git update-ref -d $REF ; done
同样适用于remotes
,但blob仍在那里。
所以我的问题:
originals
引用(可能是遥控器) - 包括所有分支和标签?答案 0 :(得分:1)
以下是额外的步骤。首先,最好注意一下你想要的blob的哈希值,这样你就可以检查它是否存在
git cat-file -t 949abcd....
好的,首先我清除了reflog,因为它仍然引用了原始克隆:
git reflog expire --expire=now --all
接下来我删除了原始远程,因为它仍然有对原始树的引用。我想如果你推送新的哈希值(可能需要强制推送)那么这个步骤将是不必要的,并且该文件最终应该最终用于GC。
git remote rm origin
接下来,我删除了original
引用(filter-branch
创建的)。我没有找到一种不那么黑客的方式:
for REF in `git show-ref | cut -c 42- | grep original` ; do git update-ref -d $REF ; done
最后,垃圾收集。我不确定--aggressive
是否必需,但--prune=now
肯定是因为否则git gc
只有垃圾收集旧不需要的对象,以确保安全。
git gc --aggressive --prune=now
在所有这些步骤git cat-file
报告blob消失后!我没有尝试将结果推回原点(重新添加之后),而且我不能100%确定上述哪些步骤是必要的,但到目前为止这似乎有效。 / p>