Gemfile.lockのマージミスってハマった話
結論を言えば、マージ気をつけましょう、以上って感じなのだけど、少し実験する。
- ruby 2.4.1
- gem 2.6.11
- bundler 1.4.16
例えば以下のような Gemfile を書いたとする。
source 'https://rubygems.org' do gem 'rake' gem 'rspec' end
これをbundle installすると、以下のような Gemfile.lock が生成される。
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.2.5)
rake (12.0.0)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
PLATFORMS
ruby
DEPENDENCIES
rake!
rspec!
BUNDLED WITH
1.14.6
DEPENDENCIES の項に、実際に記述したgem一覧が書かれていて、 GEM の項には、実際に必要となるgem(依存の依存の・・・と辿ったものを含む)とそのバージョン、そして依存treeが記載されている。
Rubyコンソールで Bundler.require すると、これらのgemがrequireされ、使えるようになっていることがわかる。
[1] pry(main)> require 'bundler'
=> true
[2] pry(main)> Bundler.require
=> [Gem::Dependency.new("rake", Gem::Requirement.new([">= 0"]), :runtime),
Gem::Dependency.new("rspec", Gem::Requirement.new([">= 0"]), :runtime)]
[3] pry(main)> Rake
=> Rake
ここで、 Gemfile.lock の GEM の項のみから rake を消してみる。
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.2.5)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
PLATFORMS
ruby
DEPENDENCIES
rake!
rspec!
BUNDLED WITH
1.14.6
人間が見ると、 GEM の項と DEPENDENCIES の項が矛盾しているが、この状態で bundle install しても、 Gemfile.lock はrakeの行が消えたままで変化しない。
この状態で、もう一度Rubyコンソールを叩いてみる。
[1] pry(main)> require 'bundler'
=> true
[2] pry(main)> Bundler.require
=> [Gem::Dependency.new("rake", Gem::Requirement.new([">= 0"]), :runtime),
Gem::Dependency.new("rspec", Gem::Requirement.new([">= 0"]), :runtime)]
[3] pry(main)> Rake
NameError: uninitialized constant Rake
from (pry):3:in `__pry__'
Bundler.require は rake を認識しているが、実際には rake はrequireされていないので、実行時エラーになる。
まとめ
git mergeするときに Gemfile.lock のマージをミスると、
- bundlerがエラーを吐いていないことを確認
- 念のため
bundle installしてみる
などをしても気づかず、実行して初めて気づくということが、起こり得るよ。