我有一个GitHub回购,有两个分支 - master&释放。
发布分支包含二进制分发文件,这些文件导致了非常大的repo大小(> 250MB),所以我决定清理它们。
首先,我通过git push origin :release
然后我删除了本地发布分支。首先我尝试git branch -d release
,但是git说“错误:分支'释放'不是你当前HEAD的祖先。”这是真的,所以我做了git branch -D release
强迫它被删除。
但我的本地和GitHub上的存储库大小仍然很大。所以,我运行了通常的git命令列表,比如git gc --prune=today --aggressive
,没有运气。
在SO 1029969跟随Charles Bailey的指示,我得到了最大blob的SHA1列表。然后我使用SO 460331中的脚本来查找blob ...并且最大的五个不存在,虽然找到了较小的blob,所以我知道脚本正在运行。
我认为这些博客是发布分支中的二进制文件,并且在删除该分支后它们会以某种方式遗留下来。什么是摆脱它们的正确方法?
答案 0 :(得分:170)
...而且没有进一步的麻烦,我可以向您呈现这个有用的命令,“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
你可能还需要先运行类似的东西哦,亲爱的,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
你可能还需要删除一些标签,谢谢Zitrax:
git tag | xargs git tag -d
我把所有这些都放在一个脚本中:git-gc-all-ferocious。
答案 1 :(得分:59)
如上所述here,只需使用
即可git reflog expire --expire-unreachable=now --all
git gc --prune=now
git reflog expire --expire-unreachable=now --all
删除reflog
中无法访问的所有提交。
git gc --prune=now
自行删除提交。
注意:仅使用git gc --prune=now
将无效,因为这些提交仍在reflog中引用。因此,清除reflog是必需的。
答案 2 :(得分:32)
如this SO answer中所述,git gc
实际上可以增加回购的大小!
现在git有一个安全机制,可以在运行“
git gc
”时立即不删除未引用的对象。
默认情况下,未引用的对象会保留2周。这是为了让您轻松恢复意外删除的分支或提交,或者避免竞争可能会被正在运行的“git gc
”进程删除正在创建但尚未引用的对象的竞争并行。因此,为了将宽限期赋予已包装但未引用的对象,重新包装过程将那些未被引用的对象推出其松散的形状,以便它们可以老化并最终被修剪。
对象变得未被引用通常不是那么多。拥有404855未引用的对象是非常多的,并且通过克隆首先发送这些对象是愚蠢的,完全浪费网络带宽。无论如何......要解决您的问题,您只需要使用
git gc
参数运行'--prune=now
'来禁用该宽限期并立即删除那些未引用的对象(仅当没有其他git活动同时发生,应该很容易在工作站上确保。顺便说一下,使用“
git gc --aggressive
”和更高版本的git(或“git repack -a -f -d --window=250 --depth=250
”)
git config pack.deltaCacheSize 1
将delta缓存大小限制为一个字节(有效禁用它),而不是默认值0,这意味着无限制。有了这个,我可以在x86-64系统上使用上面的
git repack
命令重新打包该存储库,该系统具有4GB的RAM并使用4个线程(这是一个四核)。尽管如此,驻留内存使用量增长到接近3.3GB。如果您的计算机是SMP且没有足够的RAM,那么您可以将线程数减少到只有一个:
git config pack.threads 1
此外,您可以使用
--window-memory argument
至“git repack
”进一步限制内存使用量 例如,使用--window-memory=128M
应该在delta上保持合理的上限 搜索内存使用情况虽然这可能会导致回购时的最佳delta匹配 包含许多大文件。
在过滤器分支方面,您可以考虑(谨慎)this script
#!/bin/bash
set -o errexit
# Author: David Underhill
# Script to permanently delete files/folders from your git repository. To use
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2
if [ $# -eq 0 ]; then
exit 0
fi
# make sure we're at the root of git repo
if [ ! -d .git ]; then
echo "Error: must run this script from the root of a git repository"
exit 1
fi
# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD
# remove the temporary history git-filter-branch otherwise leaves behind for a long time
rm -rf .git/refs/original/ && git reflog expire --all && git gc --aggressive --prune
答案 3 :(得分:18)
git gc --prune=now
或低级git prune --expire now
。
答案 4 :(得分:12)
每当你的HEAD移动时,git会在reflog
中跟踪它。如果你删除了提交,你仍然有“悬空提交”,因为它们仍被reflog
引用了大约30天。当您意外删除提交时,这是安全网。
您可以使用git reflog
命令删除特定提交,重新包装等,或者仅使用高级命令:
git gc --prune=now
答案 5 :(得分:4)
您可以使用git forget-blob
。
使用非常简单git forget-blob file-to-forget
。你可以在这里获得更多信息
它将从您的历史记录,reflog,标签等中的所有提交中消失
我时不时遇到同样的问题,每次我都要回到这篇文章和其他人那里,这就是为什么我要自动化这个过程。
Sam Watkins等贡献者的信用
答案 6 :(得分:2)
尝试使用git-filter-branch - 它不会删除大blob,但它可以删除您从整个repo指定的大文件。对我来说,它将repo大小从几百MB减少到12 MB。
答案 7 :(得分:1)
在执行git filter-branch
和git gc
之前,您应该查看回购协议中存在的标记。任何对持续集成和部署等事件进行自动标记的真实系统都会使这些标记仍然引用不需要的对象,因此gc
无法删除它们,您仍然会想知道为什么repo的大小仍然很大
摆脱所有不需要的东西的最佳方法是运行git-filter
& git gc
然后将主人推送到一个新的裸仓库。新的裸仓库将有清理后的树。
答案 8 :(得分:0)
有时,“gc”没有做太多好处的原因是基于旧提交存在未完成的rebase或stash。
答案 9 :(得分:0)
要添加其他提示,请不要忘记使用 git remote prune 删除遥控器的过时分支,然后再使用 git gc
你可以用 git branch -a
看到它们从github和forked存储库中获取时,它通常很有用......