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


89

我最近一次提交到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 :-(

13
只是提醒主持人,这个问题100%来自SO,而不是超级用户。
VonC


如此处所述(stackoverflow.com/questions/685319/…),在gc之后您是否尝试过重新打包? git-repack -a其次是git-prune-packed例如。参见blog.felipebalbi.com/2007/12/19/…–
VonC

2
@Jonas:在完成所有这些操作之后,如果克隆了您的仓库,该怎么办?然后,得到所需大小的克隆吗?
VonC

1
@Jonas:毕竟是你做(filter-branchgcrepack,...),不,你应该看不到任何错误提交的。这表明清洁未按预期进行。
VonC

Answers:


127

我在其他地方回答了这个问题,由于我对此感到自豪,因此将在这里复制!

...并且事不宜迟,我可以向您介绍这个有用的脚本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



18
太好了:D我邪恶的计划,通过克隆答案来获得更多积分,这很成功!! 1;)
萨姆·沃特金斯

是! 这可行,但是我必须运行完整的脚本。仅运行gc命令(带有config选项)是不够的。
丹尼尔(Daniel)

4
102m至160k ..有效而具破坏性
普鲁士旺16-3-15

4
非常感谢您的脚本!奖励信息:xargs由于无法识别的选项,该命令在OS X上产生错误。最简单的解决方案:通过自制程序安装GNU xargsbrew install findutils并替换xargsgxargs
qqilihq

26

git reflog expire --all不正确。它将删除过期时间(默认为90天)之前的reflog条目。使用git reflog expire --all --expire=now

对类似问题的回答涉及从存储库中真正清除未使用的对象的问题。


18

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

  • git rm --cached path/to/file

2)使用以下方法收缩仓库

  • git gc

  • 要么 git gc --aggressive

  • 要么 git prune

或上述问题的建议的组合:减小git存储库大小


10

可以使用相同的方法来应用有关删除敏感数据的指南。您将重写历史记录,以从存在该文件的每个修订版本中删除该文件。这是破坏性的,并且会导致与其他任何签出的存储库冲突,因此请首先警告任何协作者。

如果您想让二进制文件在其他人的仓库中可用,那么就没有真正的方法可以做您想做的事情。几乎全有或全无。


8

对我来说,关键在于运行它git repack -A -d -f,然后git gc减小了我拥有的单个git pack的大小。


6

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

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

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

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



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

记住要更改Filename要从存储库中删除的那个。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.