Gemfile.lock
.gitignore
version control
Ruby on Rails
dependency management

Should Gemfile.lock be included in .gitignore?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Whether to include Gemfile.lock in .gitignore depends on whether your project is an application or a library. Applications should always commit Gemfile.lock to ensure every developer and deployment environment uses the exact same gem versions. Libraries (gems) should gitignore it so that consumers resolve their own compatible dependency versions. This is one of the most commonly misunderstood decisions in Ruby dependency management.

Applications: Commit Gemfile.lock

For Rails apps, Sinatra apps, or any deployable application, always commit Gemfile.lock:

ruby
1# Gemfile
2source 'https://rubygems.org'
3gem 'rails', '~> 7.1'
4gem 'pg', '~> 1.5'
5gem 'puma', '~> 6.0'
bash
1# Run bundle install to generate/update Gemfile.lock
2bundle install
3
4# Commit the lock file
5git add Gemfile.lock
6git commit -m "Lock dependency versions"

Gemfile.lock records the exact version of every gem (including transitive dependencies) that was resolved. This ensures:

  • Every developer runs the same gem versions
  • CI builds are deterministic
  • Production deployments match what was tested
  • bundle install is faster (it skips resolution and installs locked versions)
bash
# On another machine, install exact locked versions
bundle install
# Installing rails 7.1.3 (exact version from lock file)

Libraries/Gems: Gitignore Gemfile.lock

For gems and libraries, add Gemfile.lock to .gitignore:

bash
# .gitignore for a gem
echo "Gemfile.lock" >> .gitignore

Why? A gem's consumers will resolve dependencies based on the .gemspec version constraints, not a lock file. Committing Gemfile.lock in a gem creates problems:

ruby
1# mylib.gemspec
2Gem::Specification.new do |spec|
3  spec.name = 'mylib'
4  spec.add_dependency 'activesupport', '>= 6.0', '< 8.0'
5end

If the gem commits a lock file pinning activesupport 7.0.4, contributors who run bundle install get that exact version instead of testing against the full supported range. This hides compatibility issues.

The Official Bundler Recommendation

From the Bundler documentation:

  • Applications: Check in Gemfile.lock
  • Gems: Do not check in Gemfile.lock
bash
1# Bundler's gem scaffold already gitignores it
2bundle gem mylib
3cat mylib/.gitignore
4# Gemfile.lock  ← automatically included

What Gemfile.lock Contains

 
1GEM
2  remote: https://rubygems.org/
3  specs:
4    actioncable (7.1.3)
5      actionpack (= 7.1.3)
6      activesupport (= 7.1.3)
7    rails (7.1.3)
8      actioncable (= 7.1.3)
9      ...
10
11PLATFORMS
12  x86_64-linux
13  arm64-darwin
14
15BUNDLED WITH
16   2.5.4

The lock file records:

  • Exact version of every gem resolved
  • Platform-specific gem selections
  • Which Bundler version generated it

Updating Gemfile.lock

bash
1# Update a specific gem
2bundle update rails
3# Resolves the latest rails matching Gemfile constraints, updates lock file
4
5# Update all gems
6bundle update
7# Re-resolves everything — can cause major version jumps
8
9# Add a new gem to Gemfile, then:
10bundle install
11# Adds the new gem to Gemfile.lock without changing existing versions
12
13# Check for outdated gems
14bundle outdated

Platform Differences

bash
1# Gemfile.lock may differ across platforms (Linux vs macOS)
2# Add all platforms you deploy to:
3bundle lock --add-platform x86_64-linux
4bundle lock --add-platform arm64-darwin-23
5
6# This prevents "Your bundle is locked to ... but that version
7# could not be found" errors on different platforms

Common Pitfalls

  • Gitignoring Gemfile.lock in an application: This causes non-deterministic builds. Two developers may get different gem versions, leading to "works on my machine" bugs. Every application should commit its lock file.
  • Committing Gemfile.lock in a gem: This pins development dependencies unnecessarily and hides compatibility issues with the version ranges declared in the .gemspec. Let CI test across multiple dependency versions instead.
  • Running bundle update without a specific gem: bundle update (with no arguments) re-resolves all gems and can introduce breaking changes. Always specify the gem name (bundle update rails) to limit the scope of changes.
  • Merge conflicts in Gemfile.lock: Never manually resolve Gemfile.lock conflicts. Instead, pick one side, then run bundle install to regenerate a valid lock file.
  • Missing platforms in lock file: If you develop on macOS but deploy to Linux, the lock file may not include Linux-specific gem versions. Run bundle lock --add-platform x86_64-linux to include them.

Summary

  • Applications (Rails, Sinatra, etc.): Always commit Gemfile.lock for deterministic builds
  • Libraries/Gems: Add Gemfile.lock to .gitignore so consumers resolve their own versions
  • Gemfile.lock records exact resolved versions of all gems including transitive dependencies
  • Use bundle update <gem> to update specific gems, not bundle update without arguments
  • Add deployment platforms with bundle lock --add-platform to avoid cross-platform issues
  • Never manually edit Gemfile.lock — let Bundler manage it with bundle install or bundle update

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.