2017-04-07 68 views
1

要删除所有提交历史的一个大的不必要的文件,您可以使用filter-branch改写每个指数(文件在回购名单)提交因此从未被添加的文件。重写提交历史修改一个文件

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,但斑点仍然存在。

所以我的问题:

  1. 有没有办法,看看为什么斑被当作垃圾回收?即父母对象在图中指向它?
  2. 是否有非哈克的方式去除originals裁判(也许该遥控器) - 包括所有的分支和标签?
  3. 还有什么我失踪?
+0

是否有包含这个大文件的_many_提交,这样手动重写历史记录不是一种现实的可能性? –

+0

是100次提交。 – Timmmm

回答

1

啊哈,我做到了!我认为。

以下是额外的步骤。首先,它是一个好主意,要注意在开始你想要的BLOB的哈希值,所以你可以检查它是否与

git cat-file -t 949abcd.... 

好了,所以我首先清除了引用日志存在,因为它仍然有原来的克隆的引用:

git reflog expire --expire=now --all 

接下来我删除了远程原点,因为它仍然有一个对原始树的引用。我猜如果你新哈希(可能需要强制推),那么这一步将是不必要的,该文件应该最终GCed无论如何。

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%确定上述哪些步骤是必要的,但这似乎工作至今。