告诉git filter-branch根据它们的blob SHA1删除文件的最佳方法是什么?
请仔细遵循使用说明,核心部分只有这个:-bi, --strip-blobs-with-ids
<blob-ids-file>
...使用指定的Git对象ID删除blobs
$ java -jar bfg.jar --strip-blobs-with-ids <blob-ids-file> my-repo.git
<blob-ids-file>
文件应包含Git对象ID,而不是纯SHA-1哈希值的内容。git hash-object
计算Git对象ID:$ git hash-object README.md
a63b49c2e93788cd71c81015818307c7b70963bf
$ sha1sum README.md
7b833f7b37550e2df719b57e8c4994c93a865aa9 README.md
那是因为Git对象ID对Git头部以及文件内容进行哈希,即使它使用相同的SHA-1算法。
BFG通常比运行git-filter-branch
快至少10-50倍,并且一般更容易使用。
完整披露:我是BFG Repo-Cleaner的作者。
--no-blob-protection
命令来禁用此功能。对于一个实时的代码库,我的建议是在进行历史记录重写之前,手动修复当前的文件树并确保一切正常。如果人们不使用我的工具来破坏他们的生产系统,那对我来说会更好!https://rtyley.github.io/bfg-repo-cleaner/#protected-commits - Roberto Tyleygit filter branch --index-filter
会将每个提交逐个放入索引中,因此可以使用git ls-files -s
从哈希中恢复文件名。
我这样做是为了删除哈希为2d341f0223ff、6a4558fa76d1和4d0a90cba061的blob:
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
随机字符串是为了避免当grep
返回无匹配时,git rm
抛出错误。
filter-branch 版本在 index-filter 中可能长这样:
git ls-files -s |
sed -r '/ 02c97746d64fbfe13007a1ab4e9b9e4bbd99f42f /s/^100(644|755)/0/' |
git update-index --index-info
正如@RobertTyley在他的答案中所指出的那样,你最好使用BFG。但是,为了回答提出的问题(如何使用filter-branch
实现此目的):
遗憾的是没有一个很好的方法。您可以编写一个脚本来获取与索引中SHA值相关联的所有文件名。作为一个起点,如果您要删除一个哈希DEADC0DE的文件。
git rev-list -n 1 --objects HEAD |grep ^DEADC0DE |cut -c 42-
然后您可以将每行(也许使用 xargs
?)作为 <filename>
输入到中。
git rm --cached <filename>
你可以将该脚本用作你的index-filter
值(因为将其用作树过滤器只会使本来就慢的方法变得更慢)。