如何从 git 存储库中删除未使用的对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3797907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to remove unused objects from a git repository?
提问by Jonas H.
I accidentally added, committed and pushed a huge binary file with my very latest commit to a Git repository.
我不小心添加、提交并推送了一个巨大的二进制文件,其中包含我对 Git 存储库的最新提交。
How can I make Git remove the object(s) that was/were created for that commit so my .git
directory shrinks to a sane size again?
如何让 Git 删除为该提交创建的对象,以便我的.git
目录再次缩小到合理的大小?
Edit: Thanks for your answers; I tried several solutions. None worked. For example the one from GitHub removed the files from the history, but the .git
directory size hasn't decreased:
编辑:感谢您的回答;我尝试了几种解决方案。没有一个工作。例如 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 :-(
回答by Sam Watkins
I answered this elsewhere, and will copy here since I'm proud of it!
我在别处回答了这个问题,我会在这里复制,因为我为此感到自豪!
... and without further ado, may I present to you this useful script, git-gc-all, guaranteed to remove all your git garbage until they might come up with extra config variables:
...不用多说,我可以向您展示这个有用的脚本 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 "$@"
The --aggressive option might be helpful.
--aggressive 选项可能会有所帮助。
NOTE: this will remove ALL unreferenced thingies, so don't come crying to me if you decide later that you wanted to keep some of them!
注意:这将删除所有未引用的东西,所以如果您以后决定要保留其中的一些,请不要向我哭泣!
You might also need to run something like these first, oh dear, git is complicated!!
您可能还需要先运行类似的东西,哦,天哪,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
I put all this in a script, here:
我把所有这些放在一个脚本中,在这里:
回答by Josh Lee
Your git reflog expire --all
is incorrect. It removes reflog entries that are older than the expire time, which defaults to 90 days. Use git reflog expire --all --expire=now
.
你git reflog expire --all
的不正确。它会删除早于过期时间(默认为 90 天)的 reflog 条目。使用git reflog expire --all --expire=now
.
My answerto a similar question deals with the problem of really scrubbing unused objects from a repository.
我对类似问题的回答涉及从存储库中真正清除未使用对象的问题。
回答by Jamie
1) Remove the file from the git repo (& not the filesystem) :
1)从git repo(而不是文件系统)中删除文件:
git rm --cached path/to/file
git rm --cached path/to/file
2) Shrink the repo using:
2)使用以下方法收缩回购:
git gc
,or
git gc --aggressive
- or
git prune
git gc
,或者
git gc --aggressive
- 或者
git prune
or a combination of the above as suggested in this question: Reduce git repository size
或以上问题的组合:Reduce git repository size
回答by Daenyth
This guide on removing sensitive datacan apply, using the same method. You'll be rewriting history to remove that file from every revision it was present in. This is destructive and will cause repo conflicts with any other checkouts, so warn any collaborators first.
可以使用相同的方法应用有关删除敏感数据的指南。您将重写历史记录以从它存在的每个修订版中删除该文件。这是破坏性的,会导致与任何其他检出的 repo 冲突,因此请先警告任何合作者。
If you want to keep the binary available in the repo for other people, then there's no real way to do what you want. It's pretty much all or none.
如果您想让其他人在 repo 中使用二进制文件,那么没有真正的方法可以做您想做的事。它几乎全部或没有。
回答by Andrew Charneski
The key for me turned out to be running git repack -A -d -f
and then git gc
to reduce the size of the single git pack I had.
对我来说,关键是运行git repack -A -d -f
,然后git gc
减少我拥有的单个 git 包的大小。
回答by u-foka
Hy!
嗨!
Git only receives objects it actually needs when cloning repositories (if I understand it correctly)
Git 只在克隆存储库时接收它实际需要的对象(如果我理解正确的话)
So you can amend the last commit removing the file added by mistake, then push your changes to the remote repository (with -f option to overwrite the old commit on the server too)
因此,您可以修改最后一次提交删除错误添加的文件,然后将您的更改推送到远程存储库(使用 -f 选项也可以覆盖服务器上的旧提交)
Then when you make a new clone of that repo, it's .git directory should be as small as before the big file(s) committed.
然后,当您创建该 repo 的新克隆时,它的 .git 目录应该与提交大文件之前一样小。
Optionally if you want to remove the unnecessary files from the server too, you can delete the repository on the server and push your newly cloned copy (that has the full history)
(可选)如果您也想从服务器中删除不必要的文件,您可以删除服务器上的存储库并推送您新克隆的副本(具有完整历史记录)
回答by Czarek Tomczak
See "Removing Objects" in the Pro Git book:
请参阅 Pro Git 书中的“移除对象”:
http://git-scm.com/book/en/Git-Internals-Maintenance-and-Data-Recovery#Removing-Objects
http://git-scm.com/book/en/Git-Internals-Maintenance-and-Data-Recovery#Removing-Objects
Update: see also BFG repo cleaner: http://rtyley.github.io/bfg-repo-cleaner/
更新:另见 BFG 回购清洁器:http: //rtyley.github.io/bfg-repo-cleaner/
回答by Martin
git filter-branch --index-filter 'git rm --cached --ignore-unmatch Filename' --prune-empty -- --all
Remember to change Filename
for the one you want to remove from the repository.
请记住更改Filename
要从存储库中删除的那个。