减少仓库大小

随着时间的推移,Git 仓库变得更大。将大文件添加到 Git 仓库时:

  • 获取仓库变得更慢,因为每个人都必须下载文件。
  • 它们占用了服务器上的大量存储空间。
  • 达到 Git 仓库存储限制。

重写仓库可以删除不需要的历史记录以缩小仓库。 我们推荐 git filter-repo 而不是 git filter-branchBFG

caution 重写仓库历史是一种破坏性操作。在开始之前,请确保备份您的仓库。备份仓库的最佳方法是导出项目

从仓库历史记录中清除文件

要减少极狐GitLab 中存储库的大小,您必须首先从由极狐GitLab 自动创建的分支、标签其他内部引用 (refs) 中删除对大文件的引用。这些 refs 包括:

  • refs/merge-requests/*:合并请求。
  • refs/pipelines/*:流水线
  • refs/environments/*:环境。
  • refs/keep-around/* 被创建为隐藏的 refs,以防止数据库中引用的提交被删除。

这些 ref 不会自动下载,也不会公布隐藏的 ref,但我们可以使用项目导出删除这些 ref。

caution 此过程不适合从仓库中删除敏感数据,例如密码或密钥。有关提交的信息(包括文件内容)缓存在数据库中,即使从仓库中删除后仍然可见。

从极狐GitLab 仓库中清除文件:

  1. 使用支持的包管理器或从源代码安装 git filter-repogit-sizer

  2. 生成一个新的项目导出 并下载它。此项目导出包含您的存储库 refs 的备份副本,我们可用于从您的仓库中清除文件。

  3. 使用 tar 解压备份: shell tar xzf project-backup.tar.gz

    包含一个由 git bundle 创建的 project.bundle 文件。

  4. 使用 --bare--mirror 选项从包中克隆一个新的仓库副本:

    git clone --bare --mirror /path/to/project.bundle
    
  5. 导航到 project.git 目录:

    cd project.git
    
  6. 因为从包文件克隆会将 origin 远端设置为本地包文件,所以将其更改为您的代码仓库的 URL:

    git remote set-url origin https://gitlab.example.com/<namespace>/<project_name>.git
    
  7. 使用 git filter-repogit-sizer,分析您的仓库并查看结果,确定您要清除哪些项目:

    # Using git filter-repo
    git filter-repo --analyze
    head .git/filter-repo/analysis/*-{all,deleted}-sizes.txt
    
    # Using git-sizer
    git-sizer
    
  8. 使用相关的 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 文档获取更多示例和完整文档。

  9. 因为您正在尝试删除内部 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 命令时,重复此步骤和所有后续步骤(包括代码仓库清理步骤)。

  10. 强制推送您的更改以覆盖极狐GitLab 上的所有分支:

    git push origin --force 'refs/heads/*'
    

    受保护的分支 会导致失败。要继续,您必须移除分支保护、推送,然后重新启用受保护的分支。

  11. 要从标签版本中删除大文件,请强制将您的更改推送到极狐GitLab 上的所有标签:

    git push origin --force 'refs/tags/*'
    

    受保护的标签 会导致失败。要继续,您必须移除标签保护、推送,然后重新启用受保护的标签。

  12. 为了防止不再存在的提交的死链接,推送由 git filter-repo 创建的 refs/replace

    git push origin --force 'refs/replace/*'
    

有关其工作原理的信息,请参阅 Git replace 文档。

  1. 等待至少 30 分钟,因为仓库清理流程只处理超过 30 分钟的对象。
  2. 运行仓库清理

仓库清理

仓库清理允许您上传对象的文本文件,极狐GitLab 删除对这些对象的内部 Git 引用。 您可以使用 git filter-repo 生成可与仓库清理一起使用的对象列表(在 commit-map 文件中)。

引入于 13.6 版本,安全清理仓库需要在操作期间将其设为只读。这会自动发生,但如果任何写入正在进行,则提交清理请求将失败,因此在继续之前取消任何未完成的 git push 操作。

要清理仓库:

  1. 转到仓库的项目。
  2. 导航到 设置 > 仓库
  3. 上传对象列表。例如,由git filter-repo 创建的 commit-map 文件位于 filter-repo 目录中。

    如果您的 commit-map 文件大于 250KB 或 3000 行,则可以将文件拆分并逐个上传:

    split -l 3000 filter-repo/commit-map filter-repo/commit-map-
    
  4. 点击开始清理

这样:

  • 删除对旧提交的任何内部 Git 引用。
  • 对仓库运行 git gc --prune=30.minutes.ago,删除未引用的对象。临时重新打包仓库会导致仓库的大小显著增加,因为在创建新的打包文件之前不会删除旧的打包文件。
  • 取消连接到项目的任何未使用的 LFS 对象,释放存储空间。
  • 重新计算磁盘上仓库的大小。

清理完成后,极狐GitLab 会发送一封电子邮件通知,其中包含重新计算的仓库大小。

如果存储库大小没有减少,这可能是由于松散对象被保留,因为它们在过去 30 分钟内发生的 Git 操作中被引用。在仓库休眠至少 30 分钟后,尝试重新运行这些步骤。

使用仓库清理时,请注意:

  • 缓存项目统计信息。您可能需要等待 5-10 分钟才能看到存储利用率的降低。
  • 清理超过 30 分钟的松散对象。这意味着不会立即删除过去 30 分钟内添加或引用的对象。如果您有权访问 Gitaly 服务器,您可以跳过延迟并立即地运行 git gc --prune=now 来清理所有松散的对象。
  • 这个过程从极狐GitLab 缓存和数据库中删除了重写提交的一些副本,但覆盖范围仍然存在许多差距,并且一些副本可能会无限期地持续存在。清除实例缓存可能有助于删除其中一些,但出于安全目的不应依赖它!

存储限制

仓库大小限制:

  • 可以在私有化部署实例上由管理员设置

当项目达到其大小限制时,您不能:

  • 推送到项目。
  • 创建一个新的合并请求。
  • 合并现有的合并请求。
  • 上传 LFS 对象。

您仍然可以:

  • 创建新议题。
  • 克隆项目。

如果超过仓库大小限制,您可以:

  1. 删除一些数据。
  2. 进行新的提交。
  3. 推送回仓库。

如果这些操作还不够,您还可以:

  • 将一些 blob 移动到 LFS。
  • 从历史中删除一些旧的依赖更新。

不幸的是,此工作流程不起作用。删除提交中的文件实际上并没有减少仓库的大小,因为较早的提交和 blob 仍然存在。相反,您必须改写历史。我们推荐开源社区维护工具 git filter-repo

note 在极狐GitLab 端运行 git gc 之前,“删除”的提交和 blob 仍然存在。您还必须能够将重写的历史记录推送到极狐GitLab,如果您已经超过最大大小限制,这可能是不可能的。

为了解除这些限制,私有化部署实例的管理员必须增加超过它的特定项目的限制。因此,主动保持在限制之下总是更好。如果您达到了限制,并且无法暂时增加,您唯一的选择是:

  1. 在本地修剪所有不需要的东西。
  2. 在极狐GitLab 上创建一个新项目并开始使用它。

故障排查

GUI 中显示的仓库统计信息不正确

如果显示的大小或提交数量与导出的 .tar.gz 或本地仓库不同,您可以要求极狐GitLab 管理员强制更新