Question
In a Rails application, Bundler manages dependencies. A gem from a Git repository is declared in the Gemfile like this:
gem "gem-name", git: "path/to/my/gem.git"
Running bundle update updates this gem but also updates other gems listed in the Gemfile. What command updates only this specific gem?
Short Answer
You will learn how Bundler uses Gemfile.lock to keep dependency versions stable and how to request an update for one named gem with bundle update gem-name. You will also see what “only one gem” means in practice: Bundler may update that gem's required dependencies when necessary to produce a valid dependency set.
Concept
Bundler manages a Ruby application's dependencies as a set of compatible versions.
- The
Gemfilestates what your application is allowed to use. - The
Gemfile.lockrecords the exact versions and Git revisions currently selected. bundle installnormally installs the versions already recorded in the lockfile.bundle updateasks Bundler to resolve newer versions and write a new lockfile.
To update one gem, pass its gem name to bundle update:
bundle update gem-name
For a Git-based dependency, Bundler fetches the configured repository and can move the lockfile from its current commit revision to a newer revision on the configured branch or ref.
The name after bundle update must be the gem's name—the name declared by the gem's .gemspec—not necessarily the Git repository name.
Although this is a targeted update, Bundler cannot promise that exactly one line of the lockfile will change. If the new version of gem-name needs a newer compatible dependency, Bundler may update that dependency too. This preserves a working, compatible bundle.
Mental Model
Think of the lockfile as a saved shopping list with exact product versions.
bundle installbuys exactly what is on the saved list.bundle updatethrows away the saved choices and rebuilds much of the list with newer products.bundle update gem-namesays: “Replace this one product with its latest compatible version, while keeping the rest of the list as stable as possible.”
If the replacement needs a different compatible accessory, Bundler is allowed to replace that accessory as well. It must make sure the whole cart still fits together.
Syntax and Examples
The targeted-update syntax is:
bundle update GEM_NAME
For example:
bundle update gem-name
A modern Git dependency declaration looks like this:
# Gemfile
gem "gem-name", git: "https://example.com/team/gem-name.git"
After running the update, inspect the changes:
git diff Gemfile.lock
For a Git gem, the lockfile contains a GIT section with a revision. A successful targeted update may change that revision:
GIT
remote: https://example.com/team/gem-name.git
revision: a_new_commit_sha
specs:
gem-name (1.2.0)
If you want to restrict the dependency changes even more, use Bundler's conservative mode:
bundle update gem-name --conservative
This tells Bundler to prefer keeping indirect dependencies at their currently locked versions when possible. It still cannot keep a dependency unchanged if the requested gem version requires a change.
Step by Step Execution
Suppose the project currently has this dependency:
# Gemfile
gem "reporting_tools", git: "https://github.com/example/reporting_tools.git"
Its lockfile currently records commit 111aaa:
GIT
remote: https://github.com/example/reporting_tools.git
revision: 111aaa
specs:
reporting_tools (2.0.0)
Run:
bundle update reporting_tools
Bundler then works through these steps:
- It reads
Gemfileand sees thatreporting_toolscomes from Git. - It reads
Gemfile.lockand sees the currently locked revision,111aaa. - It fetches information from the configured Git remote.
- It resolves a newer compatible revision of
reporting_tools. - It checks whether that revision's dependencies are compatible with the rest of the bundle.
- It writes the selected revision, and any necessary dependency changes, to
Gemfile.lock. - It installs the resolved gems locally.
The resulting lockfile might contain:
GIT
remote: https://github.com/example/reporting_tools.git
revision: 222bbb
specs:
reporting_tools (2.1.0)
Finally, run the relevant test suite before committing the lockfile change.
Real World Use Cases
Targeted gem updates are useful when you want a small, reviewable dependency change.
- Bug fix from an internal Git gem: A teammate pushes a fix to a shared library repository, and your Rails app needs that newer commit.
- Security maintenance: Update a vulnerable direct dependency without intentionally refreshing the entire dependency tree.
- Incremental upgrades: Update one integration gem, run its tests, and deal with compatibility issues before updating others.
- Production incident response: Pull in a specific library fix while minimizing unrelated changes before deploying.
- Dependency review: Create a focused pull request where reviewers can inspect the changed lockfile entries and test results.
Real Codebase Usage
In real Ruby projects, developers usually make dependency updates deliberately and commit the resulting lockfile.
Update a direct dependency
bundle update nokogiri
Then review the lockfile:
git diff -- Gemfile.lock
Keep updates narrow
When a project has a large dependency graph, conservative mode can reduce unnecessary indirect updates:
bundle update nokogiri --conservative
Pin a Git gem to a known commit
A moving branch is convenient during development but less reproducible. For a deliberate, repeatable deployment, pin a Git dependency to a commit:
gem "reporting_tools",
git: "https://github.com/example/reporting_tools.git",
ref: "222bbb333ccc444ddd"
After changing the Gemfile, run:
bundle install
Typical team workflow
- Update the intended gem.
- Review
Gemfile.lockfor unexpected changes. - Run tests, linting, and any affected integration checks.
- Commit both
Gemfilechanges, if any, andGemfile.lock.
Applications generally commit Gemfile.lock so local development, CI, and production use the same resolved dependency versions.
Common Mistakes
Running a full update unintentionally
bundle update
This may update many gems because no target was specified.
Use this instead:
bundle update gem-name
Expecting bundle install to fetch the newest Git commit
bundle install
When Gemfile.lock exists and the Gemfile has not changed, this normally installs the locked Git revision. It does not mean “get the latest commit.” Use a targeted update to refresh the Git revision.
Using the repository name instead of the gem name
The repository could be named reporting-tools-ruby, while its gemspec contains:
Gem::Specification.new do |spec|
spec.name = "reporting_tools"
end
The correct command is:
bundle update reporting_tools
Assuming no indirect dependencies can change
A targeted update is narrower than a full update, but a new gem version may require a compatible newer version of another gem. Review Gemfile.lock rather than assuming only one entry changed.
Ignoring the lockfile
Do not update locally and forget to commit Gemfile.lock. Other developers and CI may otherwise continue using the old version or resolve a different set of dependencies.
Using an unstable Git branch without awareness
A declaration that follows a branch can change whenever new commits are pushed:
gem "gem-name", git: "https://example.com/gem-name.git", branch: "main"
This is acceptable for some workflows, but pinning a ref is safer when reproducibility matters.
Comparisons
| Command or approach | What it does | Best use |
|---|---|---|
bundle install | Installs versions and Git revisions already locked, unless the Gemfile changed. | Setting up a project or reproducing the current bundle. |
bundle update | Re-resolves and may update the whole dependency set. | Planned broad dependency maintenance. |
bundle update gem-name | Updates the named gem and any dependencies that must change for compatibility. | A focused gem update. |
bundle update gem-name --conservative | Attempts to keep indirect dependencies locked where possible. | Minimizing lockfile movement in a large project. |
Git dependency with branch: | Follows the current commit on a branch when updated. | Active development against a branch. |
Git dependency with ref: | Uses one specific Git commit. | Reproducible builds and controlled releases. |
Cheat Sheet
# Update one gem
bundle update gem-name
# Update one gem while preferring locked indirect dependencies
bundle update gem-name --conservative
# Install exactly what the lockfile currently specifies
bundle install
# Inspect dependency-lockfile changes
git diff -- Gemfile.lock
# Git dependency
gem "gem-name", git: "https://example.com/org/gem-name.git"
# Follow a particular branch
gem "gem-name", git: "https://example.com/org/gem-name.git", branch: "main"
# Pin one exact commit for repeatability
gem "gem-name", git: "https://example.com/org/gem-name.git", ref: "commit-sha"
- Use the gemspec's gem name in
bundle update GEM_NAME. - Commit
Gemfile.lockfor applications. - A targeted update can still update required indirect dependencies.
- Test after changing dependencies.
FAQ
How do I update only one gem with Bundler?
Run:
bundle update gem-name
Replace gem-name with the dependency's actual gem name.
Does bundle update gem-name update every gem?
It targets the named gem. However, Bundler may also update dependencies required to make the selected version compatible with the bundle.
How do I update a Git-based gem to the latest commit?
Run bundle update with that gem's name. Bundler fetches the configured repository and updates the revision stored in Gemfile.lock when a newer compatible revision is available.
Why does bundle install not update my Git gem?
bundle install normally respects the revision already recorded in Gemfile.lock. Use bundle update gem-name to request a newer revision.
What name should I pass to bundle update?
Use the name from the gem's .gemspec, such as reporting_tools. It may differ from the repository or folder name.
Can I prevent all indirect dependency updates?
Not always. If the new version requires another dependency to change, Bundler must change it. --conservative can reduce unnecessary indirect updates:
bundle update gem-name --conservative
Should Gemfile.lock be committed in a Rails app?
Yes. Committing it makes development, CI, and deployments use the same resolved dependency versions and Git revisions.
Mini Project
Description
Create a small dependency-maintenance checklist for a Rails application that uses both a RubyGems dependency and an internal Git-hosted gem. The exercise demonstrates a focused Bundler update, lockfile review, and a reproducible Git dependency pin.
Goal
Update only the internal Git gem, verify the lockfile change, and pin the selected revision for a repeatable build.
Requirements
Use a Gemfile containing one normal gem and one Git-hosted gem.
Run a targeted update for the Git-hosted gem only.
Review the Gemfile.lock diff before accepting the update.
Pin the Git dependency to the revision selected by Bundler.
Run bundle install after changing the pin.
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.