Git 仓库瘦身

Git 仓库瘦身

随着时间的推移,Git 存储库变得越来越大,或者自己误操作,把 node_moduoles.yarn.DS_Sore 这种大文件上传到远程仓库中,虽然后期把他们移除了,但还是会使仓库体积变大,获取仓库变得更慢,每个人都必须下载文件,因此我们需要缩减 Git 仓库体积。

(虽然我们可以使用 git clone --depth=1 --single-branch https://gitlab.example.com/<namespace>/<project_name>.git ,快速拉取代码,但依然减少不了远程仓库体积)

前置条件

  1. 安装 git-filter-repo (重写仓库删除不需要的历史记录以缩小仓库,更多用法参考Examples)

    1
    $ brew install git-filter-repo
  2. 分析现有仓库 top 100 大文件

    1
    $ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -100 | awk '{print $1}')"

    示例如下,运行du -sh可以看到当前仓库大小为 82M

    image-20221117105116119

    .git文件夹为81M

    image-20221117110359777

​ 当前仓库 top 100 的大文件:

image-20221117105553946

可以看出,大文件多数集中在.yarn文件夹内。 而这个文件夹对于我们来说,是不需要使用 git 管理的。 应该是早期不规范或者误操作给上传到了仓库里。 虽然这个文件夹现在已经被删除了,但是提交记录还在。

瘦身操作

前期准备工作我们已经完成了,目的很明确,清楚历史中的.yarn文件,接下来开始瘦身工作。

  1. Export project

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

image-20221117110458641

  1. 使用 tar 解压刚才的导出项目

    1
    $ tar xzf project-backup.tar.gz

    image-20221117111010306

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

    1
    $ git clone --bare --mirror /path/to/project.bundle

    image-20221117111122563

  3. 导航到 project.git 目录

    image-20221117112940429

  4. 使用 git filter-repo ,分析您的仓库并查看结果,确定您要清除哪些项目:(可以忽略,前面已确定要删除的文件为.yarn)

    1
    $ git filter-repo --analyze
  5. 使用 git filter-repo 清除仓库历史记录中的文件。因为我们试图删除内部 refs,所以我们依靠每次运行产生的 commit-map 来告诉我们要删除哪些内部 refs。

    清除特定文件:.yarn(更多用法参考Examples)

    1
    $ git filter-repo --path-glob '.yarn/*' --invert-paths --force

    image-20221117112350330

    移除文件之后,可以发现本地仓库大小已缩减至 1M,瘦身很明显

    image-20221117112651822

    git filter-repo 每次运行都会创建一个新的 commit-map 文件,并覆盖上一次运行中的 commit-map每次运行都需要此文件。每次运行 git filter-repo 时都执行下一步。

变更远程仓库

前面操作的都是本地文件,需要提交变更记录到远程。

  1. 因为从包文件克隆会将 origin 远端设置为本地包文件,删除这个 origin 远端,并将其设置为您的仓库的 URL:

    1
    2
    $ git remote remove origin
    $ git remote add origin https://gitlab.example.com/<namespace>/<project_name>.git
  2. 强制推送你的更改以覆盖 GitLab 上的所有分支:

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

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

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

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

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

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

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

📢

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

仓库清理

上传 commit-map 文件,这个文件是git filter-repo执行过程中生成的,点击开始清理

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

1
$ split -l 3000 filter-repo/commit-map filter-repo/commit-map-

image-20221117114155484

image-20221117113956285

最后

等待远程仓库清理完成之后,我们再重新 clone 一份代码,可以很明显的发现克隆速度变快了许多,仓库体积减小了

瘦身前:

image-20221117125549419

image-20221117125812658
image-20221117115121242瘦身后:

image-20221117125458556

image-20221117125739059

image-20221117114603482

注意 📢:

  1. 操作前通知所有人将手头代码提交到远程
  2. 开始操作后,禁止大家提交代码
  3. 操作完通知大家重新 clone
  4. 记得补充 .gitignore & 还原设置。(受保护的分支、tags 继续保护起来)

参考链接

作者

Sea

发布于

2022-11-16

更新于

2023-01-10

许可协议

评论