如何从git存储库中删除未使用的对象?

时间:2010-09-26 13:08:35

标签: git file object binary

我不小心添加,提交并推送了一个巨大的二进制文件,其中包含我对Git存储库的最新提交。

如何让Git删除为该提交创建的对象,以便我的.git目录再次收缩到理智的大小?

修改:感谢您的回答;我试过几个解决方案。没有用。例如,GitHub中的文件从历史记录中删除了文件,但.git目录大小没有减少:

$ BADFILES=$(find test_data -type f -exec echo -n "'{}' " \;)

$ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $BADFILES" HEAD
Rewrite 14ed3f41474f0a2f624a440e5a106c2768edb67b (66/66)
rm 'test_data/images/001.jpg'
[...snip...]
rm 'test_data/images/281.jpg'
Ref 'refs/heads/master' was rewritten

$ git log -p # looks nice

$ rm -rf .git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --prune
Counting objects: 625, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (598/598), done.
Writing objects: 100% (625/625), done.
Total 625 (delta 351), reused 0 (delta 0)

$ du -hs .git
174M    .git
$ # still 175 MB :-(

9 个答案:

答案 0 :(得分:111)

我在其他地方回答了这个问题,因为我为此感到骄傲,所以会在这里复制!

...而且不用多说,我可以向您展示这个有用的脚本git-gc-all,保证删除所有git垃圾,直到它们可能出现额外的配置变量:

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \
  -c gc.rerereresolved=0 -c gc.rerereunresolved=0 \
  -c gc.pruneExpire=now gc "$@"

--aggressive选项可能会有所帮助。

注意:这将删除所有未引用的东西,所以如果您稍后决定要保留其中一些内容,请不要向我哭泣!

你可能还需要先运行类似的东西哦,亲爱的,git很复杂!!

git remote rm origin
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

我把所有这些放在一个脚本中,在这里:

http://sam.nipl.net/b/git-gc-all-ferocious

答案 1 :(得分:25)

您的git reflog expire --all不正确。它会删除早于过期时间的reflog条目,默认为90天。使用git reflog expire --all --expire=now

My answer针对类似的问题处理了从存储库中真正清除未使用对象的问题。

答案 2 :(得分:16)

1)从git repo(&而不是文件系统)中删除文件:

  • git rm --cached path/to/file

2)使用以下方法收缩回购:

  • git gc

  • git gc --aggressive

  • git prune

或此问题中建议的上述内容的组合:Reduce git repository size

答案 3 :(得分:10)

removing sensitive data上的本指南可以使用相同的方法。您将重写历史记录以从其存在的每个修订版中删除该文件。这是破坏性的,并且会导致与任何其他签出的回购冲突,因此首先警告任何协作者。

如果你想让repo中的二进制文件可供其他人使用,那么就没有真正的方法来做你想要的了。它几乎全部或全部没有。

答案 4 :(得分:7)

我的关键是运行git repack -A -d -f然后git gc以减少我拥有的单个git包的大小。

答案 5 :(得分:6)

HY!

Git只接收克隆存储库时实际需要的对象(如果我理解正确的话)

因此,您可以修改上次提交删除错误添加的文件,然后将更改推送到远程存储库(使用-f选项覆盖服务器上的旧提交)

然后,当您对该repo进行新的克隆时,它的.git目录应该与提交的大文件之前一样小。

或者,如果您想从服务器中删除不必要的文件,则可以删除服务器上的存储库并推送新克隆的副本(具有完整历史记录)

答案 6 :(得分:4)

git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --prune-empty -- --all

请记住更改要从存储库中删除的Filename

答案 7 :(得分:4)

请参阅Pro Git书中的“删除对象”:

http://git-scm.com/book/en/Git-Internals-Maintenance-and-Data-Recovery#Removing-Objects

更新:另请参阅BFG回购清洁工:http://rtyley.github.io/bfg-repo-cleaner/

答案 8 :(得分:0)

在2020年,git-filter-branch的文档不鼓励使用它,并建议使用诸如git-filter-repo之类的替代方法。也可以使用instead of BFG

请注意,git书中Rewriting History上的章节尚未更新。 GitHub's recommendation都没有删除敏感数据。