skip to content

With Bundler, what is the difference between `bundle install` and `bundle update` when a committed Gemfile.lock already exists?

level: juniorimportance: must knowfreq 74%

answer

  1. the lockfile wins unless you ask
  2. install reuses locked versions
  3. edited Gemfile entry: only it re-resolves
  4. update unlocks the named gems
  5. bundle update --all for everything

basics

~20 s

bundle install installs exactly the versions Gemfile.lock records and re-resolves only gems whose Gemfile entry changed. bundle update deliberately unlocks the named gems, or every gem with --all, and moves them to the newest versions the Gemfile allows.

solid answer

~40 s

Gemfile.lock is the snapshot of a resolution. `bundle install` respects it: with an unchanged Gemfile it installs the locked versions without resolving again, and after a Gemfile edit it re-resolves only the gems you changed while every untouched gem keeps its locked version and dependencies (Bundler calls this conservative updating). `bundle update rack` is the explicit request to move: it unlocks `rack` plus its dependencies and resolves them to the newest versions the Gemfile constraints permit, then rewrites the lockfile. `bundle update --all` re-resolves everything. So a teammate, CI and production all run `bundle install` and get identical gems, and version bumps happen only when someone runs `bundle update` and commits the new Gemfile.lock.

code

bash · 11 lines
bash
# fresh clone or CI: install exactly what Gemfile.lock records
bundle install

# move one gem (and its dependencies) to the newest version the Gemfile allows
bundle update rack

# re-resolve every gem
bundle update --all

# rewrite Gemfile.lock for one gem without installing
bundle lock --update rack

go deeper

for a junior

Recall the split: bundle install reproduces the lockfile, bundle update moves versions forward. Say that Gemfile.lock is committed so every machine installs the same gems.

for a middle

Explain conservative updating: after a Gemfile edit, install re-resolves only the changed gems and keeps untouched gems with their locked dependencies, and why a targeted update also moves the named gem's dependencies.

for a senior

Show the upgrade discipline: targeted bundle update runs with reviewed lockfile diffs, bundle update --all only as a planned upgrade, and bundle lock --update when the current machine cannot install every gem.

for a principal

Frame the trade-off between small frequent targeted updates and rare bulk upgrades: review cost, blast radius of a transitive bump, and how the team owns the lockfile diff.

## What Gemfile.lock pins A **Gemfile** declares *constraints*: `gem "rack", "~> 3.2"` accepts any 3.x release from 3.2 up. A constraint alone does not name a version, so two machines resolving the same Gemfile on different days can pick different releases. Bundler's answer is **Gemfile.lock**: after it resolves the whole dependency graph, it writes the exact version of every gem, direct and transitive, into that file. Commit it, and the lockfile becomes the source of truth for *which* versions run; the Gemfile only says which versions are *acceptable*. The two everyday commands differ in how much they trust that file. ## What `bundle install` does `bundle install` is the **reproduce** command. The `bundle-install(1)` man page describes three cases: 1. **No Gemfile.lock yet** - Bundler fetches the sources, resolves every dependency, installs the gems and writes a new lockfile. 2. **Lockfile present, Gemfile unchanged** - Bundler uses the dependencies recorded in Gemfile.lock *instead of* resolving. You get byte-for-byte the same versions a teammate got. 3. **Lockfile present, Gemfile edited** - Bundler keeps the locked versions for every gem you did not touch and re-resolves only the gems you changed. The man page calls this **conservative updating**. Conservative updating treats each unchanged gem as an atomic unit *together with its locked dependencies*. If your edit needs a newer version of a dependency that an untouched gem also uses, `bundle install` refuses rather than silently moving the shared dependency; you then run `bundle update` for the gems involved. ## How install notices a Gemfile edit Bundler compares the current Gemfile with what the lockfile recorded: the `DEPENDENCIES` section, the sources, the platforms and any `path` or local `git` gemspecs. When they agree, no resolution runs at all. When they differ, Bundler prints a line such as "Found changes from the lockfile, re-resolving dependencies because the dependencies in your gemfile changed" and re-resolves only what the change requires. That is why a one-line Gemfile edit normally produces a small lockfile diff: the new or changed gem, its own dependencies, and the `DEPENDENCIES` line - nothing else. Reading that diff before committing is the cheapest check that the edit did what you meant. ## What `bundle update` does `bundle update` is the **move forward** command. It ignores the locked versions of the gems you name and resolves them again against the newest releases the Gemfile allows: - `bundle update rack` unlocks `rack` **and its dependencies**, even a dependency another gem shares, and leaves everything else locked. - `bundle update --group test` unlocks the gems declared in the `test` group. - `bundle update --all` throws away the whole locked resolution and resolves everything from scratch. - `bundle update --bundler` moves the Bundler version recorded under `BUNDLED WITH`; `--ruby` moves the locked Ruby version. A bare `bundle update` with no names still updates everything, but Bundler prints a deprecation telling you to pass `--all`; setting `update_requires_all_flag` turns the bare form into an error so nobody upgrades the world by accident. `bundle lock --update rack` performs the same re-resolution but only rewrites Gemfile.lock, without installing anything - handy on a machine that cannot build every native gem. ## Side by side | | `bundle install` | `bundle update <gems>` | `bundle update --all` | |---|---|---|---| | Unchanged gems | keep locked versions | keep locked versions | re-resolved | | Named gems | locked unless their Gemfile entry changed | unlocked with their dependencies | re-resolved | | Gemfile.lock | written only when resolution changed | rewritten | rewritten | | Typical use | clone, CI, deploy, after a Gemfile edit | a deliberate bump | periodic upgrade | ## The workflow that follows - Run `bundle install` on every fresh checkout and in CI; it does not move a locked gem you did not change. - To add a gem, edit the Gemfile (or `bundle add`) and run `bundle install`; commit **both** files. - To upgrade, run `bundle update <gem>` for a targeted bump, review the lockfile diff and run the tests. - Reserve `bundle update --all` for a planned upgrade, because it can move dozens of transitive gems at once. ## Common traps - Deleting Gemfile.lock to "fix" an install re-resolves every gem - the same effect as `bundle update --all`, with none of the review. - Expecting `bundle update rack` to touch `rack` alone: by default its dependencies move too; `--conservative` narrows that. - Expecting `bundle install --force` (alias `--redownload`) to upgrade: it reinstalls the same locked versions.

  • You loosen one gem's constraint in the Gemfile and run `bundle install`. What happens to the other gems?
    They keep their locked versions. `bundle install` re-resolves only the gem whose entry changed and treats every untouched gem as fixed together with its locked dependencies. If the new version needs a dependency that an untouched gem pins differently, install reports it cannot update, and you run `bundle update` for the gems involved.
  • What does `bundle lock --update rack` do that `bundle update rack` does not?
    It re-resolves `rack` and writes the new versions into Gemfile.lock without installing any gem. That is useful when the current machine cannot build some gem, or when you only want the lockfile diff for review; a later `bundle install` then installs what the lockfile says.

saying these in an interview costs you the question

  • bundle install always fetches the newest versions the Gemfile allows
  • bundle update only installs missing gems and leaves locked versions alone
  • Deleting Gemfile.lock is the normal way to upgrade one gem
  • bundle update rack changes rack only, never its dependencies
  • Editing one Gemfile line makes bundle install re-resolve every gem