When developing a Rails app, should you ever edit your Gemfile.lock? Easy answer: it’s no, right? Plenty of reputable sources all seem to discourage it. I myself gave that answer when asked recently. But I’ve come to learn that the answer is not a complete cut-and-dried “no”, at least not in certain circumstances.
Some background
How does the Gemfile work? A quick refresher:
- The Gemfile is a list of all gems that you want to include in the project. It is used with bundler to install, update, remove and otherwise manage your used gems.
- Bundler “provides a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed. Bundler is an exit from dependency hell, and ensures that the gems you need are present in development, staging, and production. Starting work on a project is as simple as bundle install.”
-
Simply put, we list our gems and dependencies in the Gemfile, run
bundle install
, a Gemfile.lock is generated, and our dependencies are taken care of. Right?
What happens when we bundle install
?
Quoting the bundler documentation:
Install the gems specified in your Gemfile. If this is the first time you run bundle install (and a Gemfile.lock does not exist), bundler will fetch all remote sources, resolve dependencies and install all needed gems.
If a Gemfile.lock does exist, and you have not updated your Gemfile, bundler will fetch all remote sources, but use the dependencies specified in the Gemfile.lock instead of resolving dependencies.
If a Gemfile.lock does exist, and you have updated your Gemfile, bundler will use the dependencies in the Gemfile.lock for all gems that you did not update, but will re-resolve the dependencies of gems that you did update.
No surprises here. This fits with the general understanding of Bundler and Gemfiles. But keep this in mind as you continue below, since the resolving of dependencies may mean more than you realize.
Introducing some controversy: conservative gem updates
Imagine this situation:
You run bundle update cucumber-rails
, thinking it will only update cucumber-rails
. In fact, this actually updates not just cucumber-rails
, but all of its dependencies as well, which will explode in your face when one of these dependencies release a new version with breaking API changes. This happens all too often.
Lest you think I’m all alone in this, know that I’m pulling the above example from this post from Makandra Cards, and the idea in general from more experienced developers than myself. The author of the post suggests three options for conservative gem updates, the first of which is to make changes directly to Gemfile.lock.
Crazy, right? Controversial, even? Perhaps not. To date, Bundler has not acknowledged this issue, but there’s a significant use case (edge case, perhaps) that calls for editing Gemfile.lock. Just do it conservatively. Everything in moderation.