gemfile and gemfile.lock is at centerstage for managing gem dependency. They are byproduct of bundler gem. If you are using RVM this gem is installed by default. If you are not using rvm install bundler gem first. If you are using rails 3 , it already have code in place to work with bundler, so you need not have to do anything, for Rails before 3 you need to introduce few configuration line which Iam not covering here. The detail use of bundler and its purpose is available here. The syntax for Gemfile is available here.
DIFFERENCE BETWEEN GEMFILE and GEMFILE.LOCK
1-> You write your gem needed for your project in Gemfile i,e Gemfile contain your project gem dependency. But each of these gems may have dependency on one or more other gems, So Gemfile.lock contain complete snapshot of all the gems in Gemfile along with there associated dependency.
say you add a new gem oauth to your gemfile
gem "oauth", "~> 0.4.7"But, when you run bundle install, it will install all dependency of this gem and update Gemfile.lock accordingly with below additional gems actionpack >= 2.3.5 curb >= 0.6.6.0 em-http-request >= 0.2.10 jeweler >= 0 mocha >= 0.9.8 rack >= 1.0.0 rake >= 0 typhoeus >= 0.1.13 NOTE : rubygems.org is the official ruby gem host and list all gems with there associated dependency. So If you want to know a gem dependency you can find it there.
2-> You can modify Gemfile content i,e add or delete or edit any gem anytime. But You never touch a Gemfile.lock. It should be modified automatically, when you run bundle install or bundle update command.
3-> Gemfile is used to load all the required gems when rails environment is created say when you start your server or run rake command, But Gemfile.lock is used to maintain consistency in version of gems used by different developers i,e it is loaded when someone run bundle install. Thus, When your co-developers (or you on another machine) check out your code, it will come with the exact versions of all the third-party code your application used on the machine that you last developed on (in the Gemfile.lock). When they run bundle install, bundler will find the Gemfile.lock and skip the dependency resolution step. Instead, it will install all of the same gems that you used on the original machine.
whenever, you made any change to Gemfile and commit it, not forget to commit Gemfile.lock alongwith it, otherwise it will sometime create unwanted headache to other codeveloper. I am mentioning one of my experience as example below.
-> I started a internal demo project with the default sqlit3 gem as database . On running bundle install I got below error
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
checking for sqlite3.h… no
sqlite3.h is missing. Try ‘port install sqlite3 +universal’
or ‘yum install sqlite-devel’ and check your shared library search path (the
location where your sqlite3 shared library is located).
*** extconf.rb failed ***
I sorted out the issue and committed the Gemfile and Gemfile.lock. see here for more detail on gem native extension error
-> Since, it is internal project, it get handed over to two trainee. on running bundle install, one of them reported the same error with sqlite3 , I suggested him to use mysql2 instead. He added mysql2 to gem file and simply deleted sqlite3 from it and run bundle install. It basically removed the sqlit3 gem causing the problem from Gemfile.lock. But now he committed only the Gemfile and left out Gemfile.lock .
-> when second trainee pull the code and try to run bundle install, it started failing with sqlite3 error. But to his surprise he do not find any sqlite3 gem in Gemfile.The problem is that the Gemfile.lock still having the sqlite3 in it and since bundler use Gemfile.lock to install the dependency, it is throwing the error. when the first trainee committed the Gemfile.lock which is then pulled by second trainee the problem get solved.