当然,在某些时候,您可能希望更新应用程序依赖的特定依赖项的版本。例如,您可能希望将 rails
更新到 3.0.0
最终版。重要的是,即使您要更新一个依赖项,也不意味着您希望重新解析所有依赖项并使用所有依赖项的最新版本。在我们的示例中,您只有三个依赖项,但即使在这种情况下,更新所有依赖项也会导致复杂情况。
为了说明,rails 3.0.0.rc
gem 依赖于 actionpack 3.0.0.rc
gem,而 actionpack 3.0.0.rc
gem 依赖于 rack ~> 1.2.1
(这意味着 >= 1.2.1
且 < 1.3.0
)。rack-cache
gem 依赖于 rack >= 0.4
。假设 rails 3.0.0
最终版 gem 也依赖于 rack ~> 1.2.1
,并且自 rails 3.0.0
发布以来,Rack 团队发布了 rack 1.2.2
。
如果我们天真地更新所有 gems 以更新 Rails,我们将获得 rack 1.2.2
,它满足 rails 3.0.0
和 rack-cache
的要求。但是,我们没有明确要求更新 rack-cache
,它可能与 rack 1.2.2
不兼容(无论出于何种原因)。虽然从 rack 1.2.1
更新到 rack 1.2.2
可能不会破坏任何东西,但类似的情况可能会发生,涉及更大的跳跃。(有关更详细的讨论,请参见下面的 [1])
为了避免此问题,当您更新 gem 时,bundler 不会更新该 gem 的依赖项,如果另一个 gem 仍然依赖于它。在本例中,由于 rack-cache
仍然依赖于 rack
,因此 bundler 不会更新 rack
gem。这确保了更新 rails
不会无意中破坏 rack-cache
。由于 rails 3.0.0
的依赖项 actionpack 3.0.0
仍然与 rack 1.2.1
兼容,因此 bundler 会保留它,并且 rack-cache
即使在与 rack 1.2.2
不兼容的情况下也能继续工作。
由于您最初声明了对 rails 3.0.0.rc
的依赖,如果您想更新到 rails 3.0.0
,只需将您的 Gemfile
更新为 gem 'rails', '3.0.0'
并运行
$ bundle install
如上所述,bundle install
命令始终执行保守更新,拒绝更新您在 Gemfile
中未明确更改的 gem(或其依赖项)。这意味着如果您未在 Gemfile
中修改 rack-cache
,bundler 将将其视为一个不可修改的单元,及其依赖项(rack
)。如果 rails 3.0.0
与 rack-cache
不兼容,bundler 将报告您的快照依赖项(Gemfile.lock
)与更新后的 Gemfile
之间的冲突。
如果您更新了 Gemfile
,并且您的系统已经拥有所有必要的依赖项,bundler 将在您启动应用程序时透明地更新 Gemfile.lock
。例如,如果您在 Gemfile
中添加 mysql
,并且已经在您的系统中安装了它,您可以启动应用程序而无需运行 bundle install
,bundler 将将“最后已知良好”配置持久化到 Gemfile.lock
快照中。
这在添加或更新具有最少依赖项的 gem(数据库驱动程序、wirble
、ruby-debug
)时非常有用。如果您更新具有重要依赖项(rails
)的 gem,或者许多 gem 依赖于(rack
),它可能会失败。如果透明更新失败,您的应用程序将无法启动,bundler 将打印出一条错误消息,指示您运行 bundle install
。
有时,您希望更新依赖项而不修改 Gemfile。例如,您可能希望更新到 rack-cache
的最新版本。因为您没有在 Gemfile
中声明 rack-cache
的特定版本,所以您可能希望定期获取 rack-cache
的最新版本。为此,您需要使用 bundle update
命令
$ bundle update rack-cache
此命令将 rack-cache
及其依赖项更新到 Gemfile
允许的最新版本(在本例中,是可用的最新版本)。它不会修改任何其他依赖项。
但是,如果需要,它会更新其他 gem 的依赖项。例如,如果 rack-cache
的最新版本指定了对 rack >= 1.2.2
的依赖,bundler 将更新 rack
到 1.2.2
,即使您没有要求 bundler 更新 rack
。如果 bundler 需要更新另一个 gem 依赖的 gem,它将在更新完成后通知您。
如果您想将 Gemfile 中的每个 gem 更新到最新可能的版本,请运行
$ bundle update
这将从头开始解析依赖项,忽略 Gemfile.lock
。如果你这样做,请将 git reset --hard
和你的测试套件放在手边。从头开始解析所有依赖项可能会产生意想不到的结果,尤其是在你上次完全更新后,你所依赖的许多第三方软件包都发布了新版本。