# 减少仓库大小[](#减少仓库大小 "Permalink")

随着时间的流逝，Git 存储库变得越来越大. 将大文件加到 Git 存储库后：

*   由于每个人都必须下载文件，因此获取存储库的速度变慢.
*   它们占用服务器上的大量存储空间.
*   [可以达到](#storage-limits) Git 仓库的存储限制.

重写存储库可能会删除不需要的历史记录，从而使存储库更小. [`git filter-repo`](https://github.com/newren/git-filter-repo)是用于快速重写 Git 存储库历史记录的工具，建议同时使用以下两种工具：

*   [`git filter-branch`](https://git-scm.com/docs/git-filter-branch).
*   [BFG](https://rtyley.github.io/bfg-repo-cleaner/).

**危险：**重写存储库历史记录是一种破坏性操作. 在开始之前，请确保备份您的存储库. 备份存储库的最佳方法是[导出项目](../settings/import_export.html#exporting-a-project-and-its-data) .**注意：** Git LFS 文件只能由管理员使用[Rake 任务](../../../raketasks/cleanup.html)删除. [计划](https://gitlab.com/gitlab-org/gitlab/-/issues/223621)消除此限制.

## Purge files from repository history[](#purge-files-from-repository-history "Permalink")

为了使克隆项目更快，请重写分支和标签以删除不需要的文件.

1.  使用受支持的程序包管理器或从源代码[安装`git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md) .

2.  使用`--bare`克隆存储库的新副本：

    ```
    git clone --bare https://example.gitlab.com/my/project.git 
    ```

3.  使用`git filter-repo` ，从存储库的历史记录中清除所有文件.

    要清除大文件，可以使用`--strip-blobs-bigger-than`选项：

    ```
    git filter-repo --strip-blobs-bigger-than 10M 
    ```

    要清除使用 Git LFS 存储的大文件，可以使用`--blob--callback`选项. 下面的示例使用回调从 Git LFS 指针读取文件大小，并删除大于 10MB 的文件.

    ```
    git filter-repo --blob-callback '
      if blob.data.startswith(b"version https://git-lfs.github.com/spec/v1"):
        size_in_bytes = int.from_bytes(blob.data[124:], byteorder="big")
        if size_in_bytes > 10*1000:
          blob.skip()
      ' 
    ```

    要按路径清除特定的大文件，可以组合使用`--path`和`--invert-paths`选项：

    ```
    git filter-repo --path path/to/big/file.m4v --invert-paths 
    ```

    有关更多示例和完整文档，请参见[`git filter-repo`](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES)文档.

4.  运行`git filter-repo`会删除所有遥控器. 要为您的项目还原遥控器，请运行：

    ```
    git remote add origin https://example.gitlab.com/<namespace>/<project_name>.git 
    ```

5.  强制推送更改以覆盖 GitLab 上的所有分支：

    ```
    git push origin --force --all 
    ```

    [受保护的分支](../protected_branches.html)将导致此操作失败. 要继续，您必须删除分支保护，推送，然后重新启用受保护的分支.

6.  要从标记的发行版中删除大文件，请强制将更改推送到 GitLab 上的所有标记：

    ```
    git push origin --force --tags 
    ```

    [受保护的标签](../protected_tags.html)将导致此操作失败. 要继续，您必须删除标签保护，推送，然后重新启用受保护的标签.

7.  手动执行[项目整理](../../../administration/housekeeping.html#manual-housekeeping)

**注意：**为提高性能而缓存了项目统计信息. 您可能需要等待 5 到 10 分钟才能看到存储利用率下降.

## Purge files from GitLab storage[](#purge-files-from-gitlab-storage "Permalink")

要减少 GitLab 中存储库的大小，必须删除 GitLab 内部引用以包含大文件的提交. 在完成这些步骤之前，请[从存储库历史记录中清除文件](#purge-files-from-repository-history) .

除了[分支](branches/index.html)和标签（这是一种 Git 引用）之外，GitLab 还会自动创建其他引用. 这些引用可防止在查看合并请求时死链接到提交或丢失差异. [存储库清理](#repository-cleanup)可用于从 GitLab 中删除它们.

以下内部参考文献不做广告：

*   `refs/merge-requests/*`用于合并请求.
*   `refs/pipelines/*` for [pipelines](../../../ci/pipelines/index.html#troubleshooting-fatal-reference-is-not-a-tree).
*   `refs/environments/*`用于环境.

这意味着在获取时通常不包含它们，这使得获取速度更快. 另外， `refs/keep-around/*`是隐藏的 refs，以防止与讨论相关的提交被删除并且根本无法被获取.

但是，可以从项目导出内的 Git 捆绑包访问这些引用.

1.  使用受支持的程序包管理器或从源代码[安装`git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/INSTALL.md) .

2.  [从项目中](../settings/import_export.html#exporting-a-project-and-its-data)生成一个新的[导出](../settings/import_export.html#exporting-a-project-and-its-data)并下载.

3.  使用`tar`解压缩备份：

    ```
    tar xzf project-backup.tar.gz 
    ```

    这将包含一个由[`git bundle`](https://git-scm.com/docs/git-bundle)创建的`project.bundle`文件.

4.  从包中克隆存储库的新副本：

    ```
    git clone --bare --mirror /path/to/project.bundle 
    ```

5.  使用`git filter-repo` ，从存储库的历史记录中清除所有文件. 因为我们正在尝试删除内部引用，所以我们将依靠每次运行生成的`commit-map`来告诉我们要删除哪些内部引用.

    **注意：** `git filter-repo`每次运行都会创建一个新的`commit-map`文件，并覆盖前一次运行的`commit-map` . **每次**运行都将需要此文件. 每次运行`git filter-repo`都要执行下一步.

    要清除所有大文件，可以使用`--strip-blobs-bigger-than`选项：

    ```
    git filter-repo --strip-blobs-bigger-than 10M 
    ```

    要按路径清除特定的大文件，可以组合使用`--path`和`--invert-paths`选项.

    ```
    git filter-repo --path path/to/big/file.m4v --invert-paths 
    ```

    有关更多示例和完整文档，请参见[`git filter-repo`](https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES)文档.

6.  运行[存储库清理](#repository-cleanup) .

## Repository cleanup[](#repository-cleanup "Permalink")

在 GitLab 11.6 中[引入](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19376) .

仓库清理允许您上传对象的文本文件，并且 GitLab 将删除对这些对象的内部 Git 引用. 您可以使用[`git filter-repo`](https://github.com/newren/git-filter-repo)生成对象列表（在`commit-map`文件中），该对象列表可与存储库清理一起使用.

要清理存储库：

1.  转到存储库的项目.
2.  导航 **设置>存储库** .
3.  上载对象列表. 例如，一个`commit-map`文件.
4.  Click **开始清理**.

这将：

*   删除所有对旧提交的内部 Git 引用.
*   针对存储库运行`git gc` .

完成后，您将收到一封电子邮件.

When using repository cleanup, note:

*   项目统计信息已缓存. 您可能需要等待 5 到 10 分钟才能看到存储利用率下降.
*   客房部修剪 2 周以上的松散物品. 这意味着在最近 2 周内添加的对象将不会立即删除. 如果您有权访问[Gitaly](../../../administration/gitaly/index.html)服务器，则可以运行`git gc --prune=now`立即修剪所有松散的对象.
*   此过程将从 GitLab 的缓存和数据库中删除一些重写提交的副本，但是覆盖范围仍然存在许多空白，并且某些副本可能会无限期地存在. [清除实例缓存](../../../administration/raketasks/maintenance.html#clear-redis-cache)可能有助于删除其中的一些[实例](../../../administration/raketasks/maintenance.html#clear-redis-cache) ，但出于安全考虑，不应依赖它！

## Storage limits[](#storage-limits "Permalink")

储存库大小限制：

*   可以[由管理员](../../admin_area/settings/account_and_limit_settings.html#repository-size-limit-starter-only)在自我管理实例上设置.
*   Are [set for GitLab.com](../../gitlab_com/index.html#repository-size-limit).

当项目达到其大小限制时，您不能：

*   推送到项目.
*   创建一个新的合并请求.
*   合并现有的合并请求.
*   上载 LFS 对象.

您仍然可以：

*   创造新问题.
*   克隆项目.

如果超出存储库大小限制，则可以尝试：

1.  删除一些数据.
2.  进行新的提交.
3.  推回存储库.

也许您还可以：

*   将一些斑点移到 LFS.
*   从历史记录中删除一些旧的依赖项更新.

不幸的是，该工作流程无法正常工作. 实际上，在提交中删除文件并不会减小存储库的大小，因为早期的提交和 Blob 仍然存在.

您需要做的是重写历史记录. 我们建议使用开源社区维护的工具[`git filter-repo`](https://github.com/newren/git-filter-repo) .

**注意：**在 GitLab 端运行`git gc`之前，"已删除"的提交和 blob 仍将存在. 您还必须能够将重写的历史记录推送到 GitLab，如果您已经超过最大大小限制，则可能无法实现.

为了解除这些限制，自我管理的 GitLab 实例的管理员必须增加对超出它的特定项目的限制. 因此，最好始终主动保持在限制之下. 如果您达到了极限，并且无法暂时提高极限，则唯一的选择是：

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

**Caution:** This process is not suitable for removing sensitive data like password or keys from your repository. Information about commits, including file content, is cached in the database, and will remain visible even after they have been removed from the repository.