减少仓库大小
随着时间的推移,Git 仓库变得更大。将大文件添加到 Git 仓库时:
- 获取仓库变得更慢,因为每个人都必须下载文件。
- 它们占用了服务器上的大量存储空间。
- 达到 Git 仓库存储限制。
重写仓库可以删除不需要的历史记录以缩小仓库。
我们推荐 git filter-repo
而不是 git filter-branch
和 BFG。
从仓库历史记录中清除文件
要减少极狐GitLab 中存储库的大小,您必须首先从由极狐GitLab 自动创建的分支、标签和其他内部引用 (refs) 中删除对大文件的引用。这些 refs 包括:
-
refs/merge-requests/*
:合并请求。 -
refs/pipelines/*
:流水线。 -
refs/environments/*
:环境。 -
refs/keep-around/*
被创建为隐藏的 refs,以防止数据库中引用的提交被删除。
这些 ref 不会自动下载,也不会公布隐藏的 ref,但我们可以使用项目导出删除这些 ref。
从极狐GitLab 仓库中清除文件:
-
使用支持的包管理器或从源代码安装
git filter-repo
或git-sizer
。 -
生成一个新的项目导出 并下载它。此项目导出包含您的存储库和 refs 的备份副本,我们可用于从您的仓库中清除文件。
-
使用
tar
解压备份:shell tar xzf project-backup.tar.gz
包含一个由
git bundle
创建的project.bundle
文件。 -
使用
--bare
和--mirror
选项从包中克隆一个新的仓库副本:git clone --bare --mirror /path/to/project.bundle
-
导航到
project.git
目录:cd project.git
-
因为从包文件克隆会将
origin
远端设置为本地包文件,所以将其更改为您的代码仓库的 URL:git remote set-url origin https://gitlab.example.com/<namespace>/<project_name>.git
-
使用
git filter-repo
或git-sizer
,分析您的仓库并查看结果,确定您要清除哪些项目:# Using git filter-repo git filter-repo --analyze head .git/filter-repo/analysis/*-{all,deleted}-sizes.txt # Using git-sizer git-sizer
-
使用相关的
git filter-repo
选项清除代码仓库的历史记录。两种常见的选项是:-
--path
和--invert-paths
清除特定文件:git filter-repo --path path/to/file.ext --invert-paths
-
--strip-blobs-bigger-than
清除所有大于特定大小(例如 10M)的文件:git filter-repo --strip-blobs-bigger-than 10M
请参阅
git filter-repo
文档获取更多示例和完整文档。 -
-
因为您正在尝试删除内部 refs,所以稍后您将依赖每次运行生成的
commit-map
文件,来告诉您要删除哪些内部 refs。每次运行git filter-repo
都会创建一个新的commit-map
,并覆盖上一次运行的commit-map
。您可以使用以下命令备份每个commit-map
文件:cp .git/filter-repo/commit-map ./_filter_repo_commit_map_$(date +%s)
每次运行任何
git filter-repo
命令时,重复此步骤和所有后续步骤(包括代码仓库清理步骤)。 -
强制推送您的更改以覆盖极狐GitLab 上的所有分支:
git push origin --force 'refs/heads/*'
受保护的分支 会导致失败。要继续,您必须移除分支保护、推送,然后重新启用受保护的分支。
-
要从标签版本中删除大文件,请强制将您的更改推送到极狐GitLab 上的所有标签:
git push origin --force 'refs/tags/*'
受保护的标签 会导致失败。要继续,您必须移除标签保护、推送,然后重新启用受保护的标签。
-
为了防止不再存在的提交的死链接,推送由
git filter-repo
创建的refs/replace
。git push origin --force 'refs/replace/*'
有关其工作原理的信息,请参阅 Git replace
文档。
- 等待至少 30 分钟,因为仓库清理流程只处理超过 30 分钟的对象。
- 运行仓库清理。
仓库清理
仓库清理允许您上传对象的文本文件,极狐GitLab 删除对这些对象的内部 Git 引用。 您可以使用 git filter-repo
生成可与仓库清理一起使用的对象列表(在 commit-map
文件中)。
引入于 13.6 版本,安全清理仓库需要在操作期间将其设为只读。这会自动发生,但如果任何写入正在进行,则提交清理请求将失败,因此在继续之前取消任何未完成的 git push
操作。
要清理仓库:
- 转到仓库的项目。
- 导航到 设置 > 仓库。
-
上传对象列表。例如,由
git filter-repo
创建的commit-map
文件位于filter-repo
目录中。如果您的
commit-map
文件大于 250KB 或 3000 行,则可以将文件拆分并逐个上传:split -l 3000 filter-repo/commit-map filter-repo/commit-map-
- 点击开始清理。
这样:
- 删除对旧提交的任何内部 Git 引用。
- 对仓库运行
git gc --prune=30.minutes.ago
,删除未引用的对象。临时重新打包仓库会导致仓库的大小显著增加,因为在创建新的打包文件之前不会删除旧的打包文件。 - 取消连接到项目的任何未使用的 LFS 对象,释放存储空间。
- 重新计算磁盘上仓库的大小。
清理完成后,极狐GitLab 会发送一封电子邮件通知,其中包含重新计算的仓库大小。
如果存储库大小没有减少,这可能是由于松散对象被保留,因为它们在过去 30 分钟内发生的 Git 操作中被引用。在仓库休眠至少 30 分钟后,尝试重新运行这些步骤。
使用仓库清理时,请注意:
- 缓存项目统计信息。您可能需要等待 5-10 分钟才能看到存储利用率的降低。
- 清理超过 30 分钟的松散对象。这意味着不会立即删除过去 30 分钟内添加或引用的对象。如果您有权访问 Gitaly 服务器,您可以跳过延迟并立即地运行
git gc --prune=now
来清理所有松散的对象。 - 这个过程从极狐GitLab 缓存和数据库中删除了重写提交的一些副本,但覆盖范围仍然存在许多差距,并且一些副本可能会无限期地持续存在。清除实例缓存可能有助于删除其中一些,但出于安全目的不应依赖它!
存储限制
仓库大小限制:
- 可以在私有化部署实例上由管理员设置。
当项目达到其大小限制时,您不能:
- 推送到项目。
- 创建一个新的合并请求。
- 合并现有的合并请求。
- 上传 LFS 对象。
您仍然可以:
- 创建新议题。
- 克隆项目。
如果超过仓库大小限制,您可以:
- 删除一些数据。
- 进行新的提交。
- 推送回仓库。
如果这些操作还不够,您还可以:
- 将一些 blob 移动到 LFS。
- 从历史中删除一些旧的依赖更新。
不幸的是,此工作流程不起作用。删除提交中的文件实际上并没有减少仓库的大小,因为较早的提交和 blob 仍然存在。相反,您必须改写历史。我们推荐开源社区维护工具 git filter-repo
。
git gc
之前,“删除”的提交和 blob 仍然存在。您还必须能够将重写的历史记录推送到极狐GitLab,如果您已经超过最大大小限制,这可能是不可能的。为了解除这些限制,私有化部署实例的管理员必须增加超过它的特定项目的限制。因此,主动保持在限制之下总是更好。如果您达到了限制,并且无法暂时增加,您唯一的选择是:
- 在本地修剪所有不需要的东西。
- 在极狐GitLab 上创建一个新项目并开始使用它。
故障排查
GUI 中显示的仓库统计信息不正确
如果显示的大小或提交数量与导出的 .tar.gz
或本地仓库不同,您可以要求极狐GitLab 管理员强制更新。