我发现删除文件的大多数git过滤器分支示例都是基于 filename 删除文件。我不一定想这样做。相反,我已经确定了要删除的文件的一些blob(不提交)SHA1,无论它们在存储库中的位置如何。 (由于我们的回购历史,文件往往会在不改变的情况下移动。)
告诉git filter-branch根据blob SHA1删除文件的最佳方法是什么?
答案 0 :(得分:7)
您的任务是通过哈希标识符从Git历史记录中删除blob。您可能会发现使用BFG而不是git-filter-branch
更快更容易,特别是使用--strip-blobs-with-ids
标志:
-bi,--strip-blobs-with-id
<blob-ids-file>
...使用指定的Git对象ID剥离blob
仔细遵循usage instructions,核心部分就是这样:
$ java -jar bfg.jar --strip-blobs-with-ids <blob-ids-file> my-repo.git
请注意,<blob-ids-file>
文件应包含Git对象ID,而不是blob内容的简单SHA-1哈希值。
对于给定文件,您可以使用git hash-object
计算Git对象ID:
$ git hash-object README.md
a63b49c2e93788cd71c81015818307c7b70963bf
您可以看到此值与简单的SHA-1哈希值不同:
$ sha1sum README.md
7b833f7b37550e2df719b57e8c4994c93a865aa9 README.md
...那是因为Git对象id散列了Git标题以及文件内容,即使它确实使用相同的SHA-1算法。
BFG通常比运行git-filter-branch
快至少10-50倍,并且通常更容易使用。
完全披露:我是BFG Repo-Cleaner的作者。
答案 1 :(得分:0)
filter-branch版本在index-filter中可能看起来像这样:
git ls-files -s |
sed -r '/ 02c97746d64fbfe13007a1ab4e9b9e4bbd99f42f /s/^100(644|755)/0/' |
git update-index --index-info
也就是说,读取index-info格式,找到有趣的blob并将模式设置为0(将其标记为删除),然后将其写回索引。
答案 2 :(得分:0)
正如@RobertTyley在回答中指出的那样,你最好不要使用BFG。但是,要回答问题(如何使用filter-branch
执行此操作):
不幸的是,这并不是一个好方法。您可以编写脚本以获取与索引中的SHA值关联的所有文件名。作为起点,如果您要删除带有散列DEADC0DE的文件
git rev-list -n 1 --objects HEAD |grep ^DEADC0DE |cut -c 42-
然后您将每行(可能带有xargs
?)作为<{p}}中的<filename>
。
git rm --cached <filename>
并且您将该脚本用作index-filter
值(因为将其用作树过滤器只会使速度慢的方法更慢)。
答案 3 :(得分:0)
git filter branch --index-filter
迭代地将每个提交放入索引中,因此可以使用git ls-files -s
从哈希中恢复文件名。
我这样做是为了删除带有哈希的blob 2d341f0223ff,6a4558fa76d1和4d0a90cba061:
git filter-branch --force --index-filter "git ls-files -cdmo -s | grep ' 2d341f0223ff\| 6a4558fa76d1\| 4d0a90cba061' | awk '{print $4}' | xargs git rm --cached --ignore-unmatch 656565randomstring546464" --prune-empty --tag-name-filter cat -- --all
随机字符串是为了避免git rm
在grep
返回不匹配时引发错误。