Should you add Gemfile.lock to Git?
TLDR: Yes for apps. Yes for Gems.
Do you use version control to keep track of changes to your codebase? Or do you think version control is for the cowardly and just change files in a shared team folder and hope no one else is changing it at the same time?
Of course not. You are using version control like a sane, logical programming creature. So why is there such controversy about using version control for your Gemfile.lock? Let’s dig in.
First of all, this isn’t very controversial in regards to the lock file in applications. Pretty much everyone agrees you should check that into git. Including your Gemfile.lock in version control is standard practice if you are writing an application. The top answer I found on Stack Overflow says: “Assuming you’re not writing a RubyGem, Gemfile.lock should be in your repository.”
The one that can be pretty controversial is if you should check your Gemfile.lock in when building a Ruby gem. The community view seems to have evolved on this over time. There are lots of differing opinions on this so I will try to give you an overview of the arguments about when to commit Gemfile.lock and when to add it to .gitignore.
The argument for including the Gemfile.lock
Including Gemfile.lock means that everyone is working with the exact same dependencies.
This prevents bugs from cropping up on a new teammate’s laptop because they bundle installed a slightly different set of gems than you did. They won’t pull a slightly newer gem that might be broken and have their setup break. They could be sitting there blaming themselves when it was really a gem’s fault.
This also prevents this from happening in production on a new deploy or to a new production box. Imagine if you spin up a new prod box because you are getting more traffic and it installs a newer version of some Gem. It would be difficult to track down why you were getting errors.
Bundle updates can be handled on one machine and pushed out to all the other machines.
You can (and should) specify versions of gems in your Gemfile but without the Gemfile.lock being included in Git. Then nobody else will get to benefit from your work of checking that the updated Gems still work. You should check your Gemfile for updates frequently and bundle update
where appropriate. Let’s face it though, in every app I have ever worked on any major update to the Gemfile requires a developer to run through the functionality manually to make sure the app is working. This should include running the test suite after a bundle update
but it inevitably requires running manual tests for critical functionality (usually on development, then staging, then a final check-in production). Gotta be careful and make sure the app is really, really working.
The argument against including the lock file
There is the famous Yehuda Katz article which urges you to not commit your Gemfile.lock to source control when building a gem.
Gems depend on a name and version range, and intentionally don't care about where exactly the dependencies come from. Yehuda Katz
Control versions in the Gemfile
The Gemfile should have versions set and this should prevent problems, right? So two answers to the two parts of the question:
YES - setting versions for some Gems (like Rails) will keep you on the version you want.
NO - setting versions in the Gemfile won’t prevent problems.
Minor changes in Gem versions can still introduce bugs so just limiting the Gems to minor versions won’t totally prevent errors and even patch levels can introduce bugs.
Will your testing will save you?
A counter argument can be made that a developer should be running their app/gem through testing on a new install to make sure the new development environment is set up and working correctly. The same can be said for using a CI before a deploy which should be testing with a new bundle install on every run and thus get the same dependencies as a new developer would and find any bugs. This would theoretically sort out any problems but requires the tests to be complete (raise your hand if you completely trust your tests).
The evolution of community ideals
It looks like Rails is tracking the Gemfile.lock now (and it is a gem, of course) and you can see their Gemfile.lock in master.
Tracking the Gemfile.lock also makes bisecting easier. Without the Gemfile.lock being included in git a new install of the gem might return a dependency that introduces a bug. However, this new failing code will not be associated with a commit and thus will be harder to track down than a failing test that had been introduced and committed.
It looks like Bundler has changed their tune as well. At first, they gitignored the Gemfile.lock but:
Over time, however, it became clear that this practice forces the pain of broken dependencies onto new contributors, while leaving existing contributors potentially unaware of the problem. https://github.com/bundler/bundler/issues/5879
It is now recommended for all Gems created with Bundler to check in their Gemfile.lock and they have also taken Gemfile.lock out of the generated gitignore in new gems.
Final Thoughts
You should always include your Gemfile.lock if you are writing an application. The community seems to (largely) agree that you should include it in any Gems you create as well. This will make your bisecting any problems that come from your dependents easier and ensure that the pain of updating dependencies isn’t offloaded to the consumers of the Gem.