RubyGems 导航菜单

博客

返回博客文章

撰写历史,实际上是对历史进行重写。

问题

RubyGems.org 正在失控,但问题并不在于代码,而是 git 存储库实在是太大了。每次有人想要克隆存储库时,都将需要很长时间,因为该存储库的大小超过了 500MB。代码本身并不是很大,但我们需要打包我们使用的所有宝石。你可能想知道,为什么我们需要打包 RubyGems.org 宝石依赖项。当大多数项目在部署时都可以简单地从 RubyGems.org 安装宝石。但 RubyGems.org 本身可能存在会导致其不可用的严重错误。部署此类错误的唯一方法是确保 RubyGems.org 代码库并不依赖于 RubyGems.org 服务的可用性。打包 100 多个宝石会消耗空间,而且每次都会更新新的宝石时,旧版本都会永久地保留在历史记录中。Git 是分布式源代码管理,当克隆存储库时,你将克隆与它们关联的所有分支、标签和历史记录。话虽如此,存储库只会不断增长,而且克隆也会变得越来越困难。

(参阅 GitHub 问题)

其他解决方案

运行 git clone --depth=1 将是一种更简单的解决方案。然而,此方法的问题在于,每个克隆存储库的人都必须了解 depth 标志。此方法的另一个问题是,你不会在本地克隆历史记录,因此搜索或类似 git-blame 之类的东西将无法正常工作。

解决方案

在另一个 git 存储库中创建一个单独的 vendor/cache 文件夹,并将其添加为 git 子模块。如果 vendor/cache 文件夹不属于主存储库,则该文件夹的历史记录将不会受到主存储库的跟踪。因此,随着每个宝石更新,RubyGems.org 存储库将不会大量增长。

然而,这并不能解决 600MB 的存储库问题。为了解决此问题,我们必须重写存储库的历史记录,以从历史记录中删除所有打包的文件。而这正是我们所做的。在我们重写历史记录时,我们还决定从历史记录中删除一些其他大型文件夹和文件

  • server/rubygems.html
  • rubygems.txt
  • server/rubygems.txt
  • vendor/bundler_gems
  • vendor/gems
  • vendor/rails
  • 供应商/插件

最后,我们将供应商/缓存从历史记录移至另一个存储库

为什么?

RubyGems.org 是一个开源项目,始终欢迎贡献,因此,一个较小且更快的存储库是使社区更能接近该项目的关键。

最终结果


$ git clone [email protected]:rubygems/rubygems.org-backup.git
$ du -skh .
536M    .

$ git clone [email protected]:rubygems/rubygems.org.git
$ du -skh .
11M    .

对开发的影响

每个人都必须变基

任何针对rubygems/rubygems.org拥有公关的每个人都必须针对新历史记录进行变基。在本地,这意味着rubygems/rubygems.org的克隆可以将其删除并再次克隆,或者仅git fetch --all; git pull --rebase

安装依赖项

没有改变,仍然bundle install将会完成其工作。

更新或添加新的 gem

只需将 gem 添加到Gemfile或运行bundle update gem_name,然后仅向GemfileGemfile.lock发送包含更改的公关。不再需要更新供应商/缓存文件夹或向供应商存储库发送公关。RubyGems 团队将确保更新供应商文件夹。

Arthur Nogueira Neves