Git - 删除 Blob

11
有没有一种方法或命令可以使用其ID从git中删除blob?
我使用了以下命令:
$ git rev-list --objects --all | git cat-file --batch-check='%(objectname) %(objecttype) %(rest)' | grep '^[^ ]* blob' | cut -d" " -f1,3-

并获取所有版本中的 blob 列表,例如

62f7e0df0b80bce8d0a4cb388be8988df1bec5ef NodeApplication/NodeApplication/public/javascripts/homescript.js
b1d69387fbd4d4e84bbe9eb2c7f59053c0355e11 NodeApplication/NodeApplication/iisnode/index.html
624642d6f2a86844dc145803260537be0fe40090 NodeApplication/NodeApplication/.ntvs_analysis.dat

现在我想要删除这个blob

NodeApplication/NodeApplication/.ntvs_analysis.dat. 

我该怎么做呢?


你需要使用 git filter-branch,请参考 https://help.github.com/articles/remove-sensitive-data/。 - David Duponchel
实际上,我执行了git filter和gc操作来缩小我的仓库大小,并将其推送到TFS中。TFS不允许删除文件或gc操作,因此只能重写提交记录。现在,当我从TFS克隆时,仍然是旧的大小,但提交记录已被重写(所以如果我执行筛选分支操作,则这些文件不存在)。我甚至尝试了gc操作,但仍然没有改变。 - keerthee
3个回答

3
我使用BFG cleaner清理不需要的大文件,然后进行了操作。
git reflog expire --expire=now --all
git gc --aggressive --prune=now

3
楼主在询问如何通过ID删除一个blob。如果不能直接回答问题,请考虑解释如何使用BFG--strip-blobs-with-ids命令行选项。 - vhs
1
赞扬您提到了BFG,但需要更多的解释。对于OSX:
  1. brew install bfg
  2. bfg --strip-blobs-with-ids <id>
  3. git reflog expire --expire=now --all && git gc --prune=now --aggressive
- Julian K
1
为什么要调用两次 git gc? - toolforger
https://github.com/rtyley/bfg-repo-cleaner - qwr

0

这样做的“正确”方式是使用git的垃圾回收器。

首先找到所有引用该blob的树。然后找到所有引用其中一个树的提交。

完全删除这些提交(从所有分支和标签的历史记录以及reflog中),垃圾回收器将清理blob。

在删除引用它的对象之前删除blob会损坏您的存储库。

自动化整个过程的一种简单方法是使用git filter-branch,它提供了生成替代历史记录的能力,在该历史记录中从未检入该特定文件。


我已经完成了git filter-branch,现在提交已经被重写,但是git存储库中仍然存在blobs。 - keerthee
@keerthee 请查看filter-branch的手册 - 查看标记为“缩小存储库清单”的部分。如果您正确删除了引用,清除了reflog并强制进行了gc,则垃圾将被清除。 - Borealid
实际上,我已经执行了上述操作,减小了我的仓库大小并将其推送到 TFS 仓库。TFS 不允许删除文件或进行垃圾回收,因此只有提交记录被重写。现在,当我从 TFS 克隆时,它仍然是旧的大小,但提交记录已被重写(因此如果我执行筛选分支,则这些文件不存在)。我甚至尝试了 gc everything。 - keerthee
@keerthee 那你的问题在TFS上,而不是git上。 - Borealid
我理解,但是有没有一种方法可以清理本地克隆的存储库呢? - keerthee
显示剩余2条评论

0

如果您已经有了Blob ID,可以使用git verify-pack查找文件名(或反之亦然)

git verify-pack -v .git/objects/pack/*.idx | grep <reference_id or filename>

一旦您获得了文件名,您应该:

  • 从Git中删除所有对Blob的引用,然后
  • 使用git filter-branch重写历史记录,以便从分支的每个提交中删除Blob。

这样,Git垃圾收集器git gc将清理它并释放空间。

查看脚本git forget-blob,以一步完成所有操作

git forget-blob file-to-forget

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

基本上,这将删除所有标签、远程引用,就像这样

git tag | xargs git tag -d
git filter-branch --index-filter "git rm --cached --ignore-unmatch $FILE"
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
git for-each-ref --format="%(refname)" refs/original/ | \
  xargs -n1 --no-run-if-empty git update-ref -d
git reflog expire --expire-unreachable=now --all
git repack -A -d
git prune

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接