如何使用git filter-branch通过blob SHA1删除文件?

时间:2017-02-15 16:21:59

标签: git git-filter-branch git-rewrite-history

我发现删除文件的大多数git过滤器分支示例都是基于 filename 删除文件。我不一定想这样做。相反,我已经确定了要删除的文件的一些blob(不提交)SHA1,无论它们在存储库中的位置如何。 (由于我们的回购历史,文件往往会在不改变的情况下移动。)

告诉git filter-branch根据blob SHA1删除文件的最佳方法是什么?

4 个答案:

答案 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 rmgrep返回不匹配时引发错误。