了解Gemfile.lock文件

运行bundle install命令后,在工作目录中创build“Gemfile.lock ”。 那个文件里的指令是什么意思?

例如,让我们拿下面的文件:

 PATH remote: . specs: gem_one (0.0.1) GEM remote: http://example.org/ specs: gem_two (0.0.2) gem_three (0.0.3) gem_four (0.0.4) PLATFORMS platform DEPENDENCIES gem_two gem_one! 

PATH ”,“ GEM ”,“ PLATFORMS ”和“ DEPENDENCIES ”是什么形容的? 他们都需要吗?

什么应该包含“ 远程 ”和“ 规格 ”的子目录?

DEPENDECIES ”组中的gem名称之后的感叹号是什么意思?

您可以在打包商网站上find更多关于它的信息 (为了您的方便,在下面着重强调):

在开发你的应用程序一段时间后,检查应用程序连同Gemfile和Gemfile.lock快照。 现在,您的存储库中logging了您上一次确定应用程序正常工作时使用的所有gem的确切版本。

这一点很重要: Gemfile.lock使您的应用程序成为您自己的代码和上次运行的第三方代码的一个包,确保一切正常。 在您的Gemfile中指定您所依赖的第三方代码的确切版本将不会提供相同的保证,因为gems通常会为其依赖项声明一系列版本。

关于感叹号,我刚刚发现它是通过:git获取的gem,例如

 gem "foo", :git => "git@github.com:company/foo.git" 

在我看来,像PATH直接从你的gemspec列出第一代依赖,而GEM列出了第二代依赖(即你的依赖依赖)和你的Gemfile。 PATH :: remote是. 因为它依靠当前目录中的本地gemspec来查找属于PATH :: spec的内容,而GEM :: remote是rubygems.org ,因为这是它必须去查找属于GEM :: spec的内容。

在Rails插件中,您将看到一个PATH部分,但不在Rails应用程序中。 由于该应用程序没有gemspec文件,所以没有什么可以放入PATH。

至于相关内容, gembundler.com指出:

 Runtime dependencies in your gemspec are treated like base dependencies, and development dependencies are added by default to the group, :development 

rails plugin new my_plugin my_plugin生成的rails plugin new my_plugin表示了类似的内容:

 # Bundler will treat runtime dependencies like base dependencies, and # development dependencies will be added by default to the :development group. 

这意味着什么之间的区别

 s.add_development_dependency "july" # (1) 

 s.add_dependency "july" # (2) 

是(1)在开发环境中只包含Gemfile.lock中的“7月”(因此在应用程序中)。 所以当你运行bundle install ,不仅在PATH下,而且在DEPENDENCIES下也会看到“七月”,但是只在开发中。 在生产中,根本就不存在。 但是,使用(2)时,只会在PATH中看到“七月”,而不是在依赖关系中,但是在从生产环境中bundle install时(即将其作为依赖关系包含在其他某个gem中) ,不仅仅是发展。

这些只是我的观察,我不能完全解释为什么这是这样,但我欢迎进一步的意见。

Bundler是一个Gempipe理器,通过跟踪和安装所需的精确gem和版本,为Ruby项目提供一致的环境。

Gemfile和Gemfile.lock是Bundler gem提供的主要产品(Bundler本身就是一个gem)。

Gemfile包含你的项目对gem(s)的依赖,你用指定的版本手动提到,但是这些gem(s)inturn依赖于其他由bundler自动parsing的gem。

Gemfile.lock包含Gemfile中所有gem(s)的完整快照以及相关的依赖关系。

当你第一次调用bundle install的时候 ,它会创build这个Gemfile.lock,并在所有的后续调用中使用这个文件来捆绑安装,这将确保你安装了所有的依赖,并且会跳过依赖安装。

当你与不同的机器分享你的代码时也是如此

你和Gemfile一起共享你的Gemfile.lock,当你在其他机器上运行bundle install的时候,它会引用你的Gemfile.lock并跳过依赖关系parsing步骤,而不是安装所有依赖的gem(s)原始机器, 保持多台机器的一致性

为什么我们需要在多台机器上保持一致?

  • 在不同的机器上运行不同的版本可能会导致代码损坏

  • 假设你的应用程序使用了1.5.3版本,并在14个月前运行
    没有任何问题,并尝试安装在不同的机器上
    没有Gemfile.lock现在你得到的版本1.5.8。 也许它是与最新版本的gem(S)和您的应用程序将打破
    失败。 保持一致性是最重要的(首选
    实践)。

也可以使用包更新来更新 Gemfile.lock中的gem(s)。

这是基于保守更新的概念

在过去的几个月中,我花费了大量的时间来处理Gemfiles和Gemfile.locks,同时构build了一个自动的依赖关系更新工具1 。 下面的内容远不是明确的,但是理解Gemfile.lock格式是一个很好的起点。 您可能还想查看Bundler的锁文件parsing器的源代码。

您可以在Bundler 1.x生成的locking文件中find以下标题:

创业板 (可选但很常见)

这些是来自Rubygems服务器的依赖项。 这可能是Rubygems.org上的主要Rubygems索引,也可能是一个自定义索引,例如Gemfury等人提供的索引。 在本节中,您将看到:

  • remote:一行或多行指定Rubygems索引的位置
  • specs:依赖关系列表,其版本号以及任何子依赖关系的约束条件

GIT (可选)

这些是来自给定的git远程的依赖项。 你会看到每个git远程的不同的部分,在每个部分你会看到:

  • remote: git远程。 例如, git@github.com:rails/rails
  • revision: Gemfile.lock被locking的提交引用
  • tag:可选)在Gemfile中指定的标签
  • specs:在这个远程发现的git依赖,及其版本号,以及对任何子依赖的约束

PATH (可选)

这些是来自Gemfile中给定path依赖项。 对于每个path依赖关系,您将看到不同的这些部分之一,在每个部分中您将看到:

  • remote:path。 例如, plugins/vendored-dependency
  • specs:在这个远程发现的git依赖,及其版本号,以及对任何子依赖的约束

PLATFORMS

Gemfile.lock是针对Ruby平台生成的。 如果Gemfile中的任何依赖关系指定了一个平台,那么当该平台上生成locking文件(例如,通过安装)时,它们将仅包含在Gemfile.lock中。

相关内容

Gemfile中指定的依赖关系列表,以及在那里指定的版本约束。

与主Rubygems索引(例如,git依赖关系,基于path的依赖关系)不同的源指定的依赖关系具有! 这意味着他们被“固定”到源2 (尽pipe有时候必须查看Gemfile来确定)。

RUBY VERSION (可选)

创buildGemfile.lock时,在Gemfile中指定的Ruby版本。 如果在.ruby_version文件中指定了一个Ruby版本,则该部分将不存在(因为Bundler将认为Gemfile / Gemfile.lock与安装程序的Ruby版本无关)。

捆绑(Bundler> = v1.10.x)

Bundler的版本用于创buildGemfile.lock。 用于提醒安装程序更新他们的Bundler版本,如果它早于创build该文件的版本。

插件源 (可选,非常罕见)

理论上,一个Gemfile可以指定Bundler插件,以及gem 3 ,然后在这里列出。 实际上,截至2017年7月,我并不知道有任何可用的插件。Bundler的这一部分仍在积极开发中!


  1. https://dependabot.com
  2. https://github.com/bundler/bundler/issues/4631
  3. http://andre.arko.net/2012/07/23/towards-a-bundler-plugin-system/

Gemfile.lock格式似乎没有明确的文档。 也许这是因为Gemfile.lock只是在内部被bundle使用。

但是,由于Gemfile.lockGemfile.lock的快照, Gemfile它的所有信息都应该来自Gemfile (如果没有在Gemfile指定, Gemfile默认值)。

对于GEM ,它列出了您直接或间接引入Gemfile中的所有依赖关系。 在GEM下的remote告诉在哪里得到gem,这是在Gemfile由源指定的。

如果gem不是从remote获取, PATH通知该位置以find它。 当声明一个依赖关系时, PATH的信息来自Gemfile path 。

PLATFORM就是从这里开始的 。

对于DEPENDENCIES ,这是通过捆绑解决的依赖关系的快照。

“DEPENDECIES”组中的gem名称之后的感叹号是什么意思?

使用非“ https://rubygems.org ”来源安装gem时,会显示感叹号。