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

busg9geu  于 2022-12-02  发布在  Git
关注(0)|答案(9)|浏览(387)

我不小心添加,提交和推送了一个巨大的二进制文件,我最近的提交到一个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 :-(
lrpiutwd

lrpiutwd1#

我在其他地方回答了这个问题,并将复制在这里,因为我为它感到自豪!
...废话不多说,我可以向你介绍这个有用的脚本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

我把这一切都写进了一个脚本,在这里:
https://ucm.dev/t/bin.git/git-gc-all-ferocious

siv3szwd

siv3szwd2#

您的git reflog expire --all不正确。它会移除超过到期时间(预设为90天)的reflog项目。请使用git reflog expire --all --expire=now
我对一个类似问题的回答涉及从存储库中真正清理未使用的对象的问题。

hs1ihplo

hs1ihplo3#

1)从git存储库(而不是文件系统)中删除文件(& N):

  • git rm --cached path/to/file

2)使用以下方法收缩存储库:

  • git gc
  • git gc --aggressive
  • git prune

或以上各项的组合,如本问题所建议:Reduce git repository size

rryofs0p

rryofs0p4#

removing sensitive data上的指南也适用,使用相同的方法。您将重写历史记录以从每个版本中删除该文件。这是破坏性的,并将导致与任何其他 checkout 的repo冲突,因此请首先警告所有合作者。
如果你想让其他人在repo中使用这个二进制文件,那么就没有真实的的方法来实现你想要的,这几乎是全部或者没有。

mrwjdhj3

mrwjdhj35#

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

qij5mzcb

qij5mzcb6#

嗨!
Git在克隆仓库时只接收它实际需要的对象(如果我理解正确的话)
因此,您可以修改最后一次提交,删 debugging 误添加的文件,然后将更改推送到远程仓库(使用-f选项也覆盖服务器上的旧提交)
然后,当你创建一个新的repo克隆时,它的.git目录应该和提交大文件之前一样小。
或者,如果您也想从服务器中删除不必要的文件,您可以删除服务器上的存储库并推送新克隆的副本(具有完整历史记录)

ecfsfe2w

ecfsfe2w7#

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

请记住将Filename更改为要从存储库中删除的文件。

k75qkfdt

k75qkfdt8#

请参阅Pro Git手册中的“移除对象”:
http://git-scm.com/book/en/Git-Internals-Maintenance-and-Data-Recovery#Removing-Objects
更新:另请参见BFG回购清理程序:http://rtyley.github.io/bfg-repo-cleaner/

zlhcx6iw

zlhcx6iw9#

在2020年,git-filter-branch的文档不鼓励使用它,并建议使用git-filter-repo这样的替代品。
注意git手册中关于Rewriting History的章节没有更新,关于删除敏感数据的GitHub's recommendation也没有更新。

相关问题