Question

Why rbenv Is Not Changing Ruby Version on macOS or Ubuntu

rubyrbenv

Question

I installed rbenv by following the GitHub instructions. I am testing on both macOS and an Ubuntu 12.04 virtual machine, and I see the same behavior in each environment.

When I try to switch Ruby versions, rbenv appears to think the global version is set correctly, but the terminal still uses the system Ruby:

rbenv versions
* 1.9.3-p0 (set by /Users/user/.rbenv/version)
  1.9.3-p125

rbenv global
# output
1.9.3-p0

rbenv rehash

ruby -v
# output
ruby 1.8.7 (2011-12-28 patchlevel 357) [universal-darwin11.0]

which ruby
# output
/usr/bin/ruby

rbenv local
# output
rbenv: no local version configured for this directory

Why is rbenv not actually switching the Ruby version, even though it reports the global version as changed?

Short Answer

By the end of this page, you will understand how rbenv selects a Ruby version, why which ruby may still point to /usr/bin/ruby, and how shell configuration and PATH determine whether rbenv works correctly. You will also learn how to diagnose and fix common rbenv setup problems on macOS and Linux.

Concept

rbenv does not replace the system Ruby directly. Instead, it works by placing shims at the front of your shell's PATH.

A shim is a small executable that stands in front of the real command. When you run a command like ruby, gem, or bundle, the shim asks rbenv which Ruby version should be active, then forwards the command to the correct Ruby installation.

If your shell is still finding /usr/bin/ruby, that means the rbenv shims are not being used first in PATH. In that case:

  • rbenv global may still show the version you selected
  • rbenv versions may still list installed Rubies
  • but ruby -v will keep showing the system Ruby

This is why rbenv can look correctly configured at first glance while not actually affecting the Ruby that runs.

The key idea is:

  • rbenv stores version settings
  • shell PATH decides whether those settings are used
  • the shims directory must be before system paths like /usr/bin

This matters in real development because many language version managers work this way, including tools for Node.js, Python, Java, and others. If you understand PATH and shims, you can debug many environment issues much faster.

Mental Model

Think of rbenv as a receptionist in front of several Ruby installations.

When you type ruby, your shell looks for the first ruby it can find.

  • If it reaches /usr/bin/ruby first, you get the system Ruby.
  • If it reaches the rbenv shim first, the receptionist checks your configured version and sends you to the correct Ruby.

So the problem is usually not that rbenv forgot your chosen version. The problem is that the shell never asked rbenv in the first place.

Take Quiz

Syntax and Examples

The most important rbenv commands are:

rbenv versions
rbenv global 3.2.2
rbenv local 3.2.2
rbenv shell 3.2.2
rbenv rehash
rbenv which ruby

A typical shell setup looks like this:

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

On newer setups, rbenv init usually adds the shims path for you. After configuration, check:

which ruby
ruby -v
rbenv which ruby

Expected result:

which ruby
# something like:
# /Users/yourname/.rbenv/shims/ruby

If you still get:

/usr/bin/ruby

then your shell is not using rbenv shims.

Example diagnosis

rbenv global 1.9.3-p125
ruby -v
which ruby
rbenv which ruby

Possible output:

ruby 1.8.7 ...
/usr/bin/ruby
/Users/user/.rbenv/versions/1.9.3-p125/bin/ruby

This tells you:

  • rbenv knows where the correct Ruby is
  • but your shell is bypassing rbenv
  • so the issue is shell setup, not the Ruby installation itself

Step by Step Execution

Consider this example:

rbenv global 1.9.3-p125
ruby -v
which ruby

Here is what happens step by step:

  1. rbenv global 1.9.3-p125

    • rbenv writes the selected version into ~/.rbenv/version.
    • This does not automatically force the shell to use that Ruby.
  2. ruby -v

    • Your shell searches the directories in PATH from left to right.
    • If /usr/bin comes before ~/.rbenv/shims, the shell runs /usr/bin/ruby.
    • You see the system Ruby version instead of the version managed by rbenv.
  3. which ruby

    • This shows the exact executable your shell found.
    • If it prints /usr/bin/ruby, rbenv shims are not active.
  4. If rbenv is configured correctly:

    • which ruby should point to ~/.rbenv/shims/ruby
    • the shim will ask rbenv which version is active
    • then it will run the matching Ruby from ~/.rbenv/versions/...

Useful debugging commands

echo $PATH
rbenv version
rbenv which ruby
type ruby

These help you answer four different questions:

  • What directories are searched? → echo $PATH
  • What version does rbenv think is active? → rbenv version
  • Where is the selected Ruby installed? → rbenv which ruby
  • What command is actually being executed? → type ruby

Real World Use Cases

This concept appears often in real development work:

  • Working on old and new Ruby apps

    • One project may need Ruby 2.7, another Ruby 3.2.
    • rbenv lets each project use the correct version.
  • Avoiding system Ruby changes

    • macOS ships with a system Ruby that other tools may rely on.
    • Version managers let you install your own Ruby safely.
  • Consistent team environments

    • Teams can commit a .ruby-version file so everyone uses the same Ruby.
  • CI and deployment setup

    • Build servers often use version managers or similar PATH-based tools.
    • Understanding shims helps when scripts work locally but fail in CI.
  • Debugging command conflicts

    • Many tools such as pyenv, nodenv, and asdf use the same idea.
    • Learning this once helps across multiple ecosystems.
Take Quiz

Real Codebase Usage

In real projects, developers usually combine rbenv with a few practical patterns:

Project-specific Ruby with .ruby-version

A codebase often includes:

.ruby-version

Example content:

3.2.2

This lets rbenv automatically switch when you enter the project directory.

Guard checks in setup scripts

Teams often add checks like:

ruby -v
bundle -v
which ruby

This catches environment mistakes early.

Early validation in documentation

Many projects include setup instructions such as:

which ruby
# should be ~/.rbenv/shims/ruby

This is a fast sanity check before installing gems or running the app.

Rehash after installing executables

After installing gems that add commands, developers run:

rbenv rehash

This regenerates shims for executables like:

  • bundle
  • rake
  • rspec
  • rails

Shell initialization patterns

A common pattern is to put rbenv setup in shell startup files such as:

  • ~/.bashrc
  • ~/.bash_profile
  • ~/.zshrc

Without this, rbenv may work in one shell session but not another.

Common Mistakes

1. Setting the global version but not initializing rbenv

This is the exact issue behind many cases like this one.

Broken situation:

rbenv global 1.9.3-p125
ruby -v
# still shows system ruby

Why it happens:

  • the version is saved
  • but the shell is not using rbenv shims

How to avoid it:

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

Then restart the shell.

2. Checking only rbenv global

Broken assumption:

rbenv global
# correct version shown

This does not prove that ruby is using that version.

Always also check:

which ruby
ruby -v

3. Forgetting that PATH order matters

If PATH contains the right directory but in the wrong position, the system Ruby still wins.

Check:

echo $PATH

The rbenv paths should appear before /usr/bin.

4. Editing the wrong shell config file

You may add rbenv setup to .bashrc while actually using zsh, or to .profile while your terminal loads .bash_profile.

How to avoid it:

echo $SHELL

Then update the matching startup file.

5. Not restarting the shell after changes

After editing shell config files, your current terminal session may still use the old environment.

Fix:

exec "$SHELL"

or close and reopen the terminal.

6. Assuming rbenv rehash changes the active Ruby

rehash only rebuilds command shims. It does not fix a bad PATH.

7. Confusing local, global, and shell versions

  • local applies in the current project directory
  • global is the fallback default
  • shell applies only in the current shell session

If a local version exists, it overrides the global one.

Comparisons

ConceptWhat it doesScopeCommon use
rbenv globalSets the default Ruby versionUser-wide fallbackPersonal default Ruby
rbenv localSets Ruby version for one directoryProject-specificApp-level Ruby version
rbenv shellSets Ruby version for current shell onlyTemporary sessionTesting a version quickly
rbenv rehashRebuilds executable shimsTooling supportAfter installing gems
which rubyShows what executable the shell will runCurrent shellDebugging PATH issues
rbenv which rubyShows the Ruby executable chosen by rbenvrbenv resolutionDebugging rbenv itself

which ruby vs rbenv which ruby

CommandMeaning
which rubyWhat your shell will run right now
rbenv which rubyWhat rbenv wants to run for the selected version

If these point to different places, your shell setup is the problem.

System Ruby vs rbenv Ruby

System Rubyrbenv Ruby
Installed by the OSInstalled by you
Usually in /usr/bin/rubyUsually in ~/.rbenv/versions/...
May be old or managed by the OSEasy to switch per project
Not ideal for app-specific developmentBest for development workflows
Take Quiz

Cheat Sheet

# Show installed Ruby versions
rbenv versions

# Set default Ruby for your user
rbenv global 3.2.2

# Set Ruby for current project
rbenv local 3.2.2

# Set Ruby only for this terminal session
rbenv shell 3.2.2

# Show active version according to rbenv
rbenv version

# Show the actual ruby command your shell runs
which ruby

# Show the ruby executable rbenv resolves to
rbenv which ruby

# Rebuild shims after installing gem executables
rbenv rehash

Required idea

rbenv only works if your shell uses its shims.

Typical shell setup

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

Healthy setup signs

which ruby
# ~/.rbenv/shims/ruby

ruby -v
# selected version

Red flag

which ruby
# /usr/bin/ruby

This means the system Ruby is still being used.

Version priority

  1. rbenv shell
  2. rbenv local
  3. rbenv global
  4. system Ruby fallback

FAQ

Why does rbenv global change the version but ruby -v does not?

Because rbenv saved the version, but your shell is still running a different ruby executable, usually /usr/bin/ruby.

How do I know if rbenv is working correctly?

Run:

which ruby
ruby -v

If which ruby points to ~/.rbenv/shims/ruby, rbenv is active.

What does rbenv rehash do?

It regenerates shims for Ruby executables provided by installed gems. It does not fix PATH or shell initialization problems.

Why does which ruby show /usr/bin/ruby?

Because your PATH is finding the system Ruby before the rbenv shims directory.

Do I need both rbenv and ruby-build?

rbenv manages version selection. ruby-build is commonly used to install Ruby versions. They are related but serve different purposes.

What is the difference between global and local in rbenv?

global sets your default Ruby version. local creates a project-specific version, usually stored in a .ruby-version file.

Does macOS system Ruby interfere with rbenv?

Not if rbenv is configured correctly. The issue is usually shell PATH order, not the existence of the system Ruby itself.

Take Quiz

Mini Project

Description

Build a small shell-based diagnostic checklist for rbenv. The goal is to practice checking version settings, shell command resolution, and PATH behavior in a repeatable way. This mirrors what developers do when onboarding to a Ruby project or debugging a broken environment.

Goal

Create a command-line checklist that confirms whether rbenv is installed, initialized, and actually controlling the ruby command.

Requirements

  • Print the current shell and current PATH.
  • Show the outputs of rbenv version, which ruby, and ruby -v.
  • Detect whether which ruby points to an rbenv shim or to the system Ruby.
  • Print a helpful message explaining the likely issue.
  • Work as a simple Bash script.
Take Quiz

Keep learning

Related questions

View more