Random fence in a field, which apparently serves little to no purpose.
Surely Chesterton would be fine with tearing down this fence? Photo attribution here.

I recently wrote a line-by-line walk-through of the RBENV shim for the bundle command (actually, the RBENV shim for every gem, since they're all the same code). The goal was to be able to explain what the syntax of each line of code does.

But there's an order-of-magnitude difference between knowing what a piece of code does, vs. knowing how and why it got to that point. Reading the repo's git history is one way to reach that 2nd level of understanding.

While I'm not proposing to read the entire git history of this repo (although the more of it we read, the more context we'd have), I do think it'd be a useful exercise to read some of its history. Specifically, enough history to answer a question we had from the walk-through, i.e. why there's a need for this if-block, which takes up 2/3 of the code in the shim file.

Prelude: Chesterton's Fence

There's a principle called "Chesterton's Fence" which I've found to be quite helpful in programming (and in life in general). It states the following:

There exists in such a case a certain institution or law; let us say, for the sake of simplicity, a fence or gate erected across a road. The more modern type of reformer goes gaily up to it and says, “I don’t see the use of this; let us clear it away.” To which the more intelligent type of reformer will do well to answer: “If you don’t see the use of it, I certainly won’t let you clear it away. Go away and think. Then, when you can come back and tell me that you do see the use of it, I may allow you to destroy it.”

In other words, "Don't tear down a fence until you know why it was built in the first place."

This principle has come in handy more times than I can count in programming. If I don't understand why a certain code block is present in the codebase, and if it strikes me as problematic in some way, I might be tempted to make a PR to remove it or replace it with something I think is "better". Chesterton's Fence tells me to reserve judgement on this code, and to hold off on making that PR, until I know the thought process which led to its introduction in the first place.

The below is an illustration of just how I do this. Especially when a codebase is old, and many contributors have come and gone over time, Github becomes an important (and possibly the only) tool that we as engineers have to communicate with each other across space and time.

I hope you're able to take something from the process I outline below, and use it to glean some additional context on your team's codebase.

What We Know So Far

In case you haven't read the deep-dive, here's the code for the if-block:

if [ "$program" = ruby ]; then
  for arg; do
    case "$arg" in
    -e* | -- ) break ;;
    */* )
      if [ -f "$arg" ]; then
        export RBENV_DIR="${arg%/*}"
        break
      fi
      ;;
    esac
  done
fi

And here's our working knowledge of what this code does.

The if clause itself checks whether the command that the user entered (i.e. the command that RBENV is intercepting via this shim) is the ruby command. If it is, we proceed with the logic inside the if-clause. If it's not, we skip that logic entirely.

Inside the if clause is a for-loop, which iterates over each argument passed to the ruby shim. For each argument, we check its value via a case statement.

If the argument is either -e or --, we break out of the for-loop, since these two arguments indicate that any subsequent arguments are parameters and are unrelated to the shim's business.

If the argument is a string containing a / character, however, we next check if that */* string represents a path to a file in our filesystem. If it does not, we do nothing. If it does, however, we set an environment variable called RBENV_DIR which is equal to that filepath, minus the file name itself (in other words, the parent directory of that file). We then break out of the for-loop, indicating that we don't care about any subsequent arguments.

But why do we need to do all the above?

Purpose of the RBENV_DIR environment variable

In the "How It Works" section of the README file, we see that if you pass the ruby command a filename to run, RBENV will look for a file named .ruby-version in the same directory as that of the filename you pass:

After rbenv injects itself into your PATH at installation time, any invocation of ruby, gem, bundler, or other Ruby-related executable will first activate rbenv. Then, rbenv scans the current project directory for a file named .ruby-version. If found, that file determines the version of Ruby that should be used within that directory. Finally, rbenv looks up that Ruby version among those installed under ~/.rbenv/versions/.

This is true even if that directory is not the one you're in now. That's important, because that 2nd directory may have its own .ruby-version file, possibly containing a different Ruby version from the one you're currently using.

Putting these pieces together, we can hypothesize that this clause handles the situation where you're running a Ruby file from a different directory than the one you're in, and this directory may have its own (potentially different) Ruby version.

Let's find the PR which added the if-block, and see if it confirms our theory.

Quick note- .ruby-version vs. .rbenv-version

As mentioned, RBENV sometimes uses on a file called .ruby-version to do its job. However, when we dig into the history of the if-block, we'll be looking at an earlier version of RBENV in which it instead used a file called .rbenv-version. This file performed the same function, but per this comment thread, the filename made it harder for folks who used RBENV to collaborate with folks who used other Ruby version managers.

Because of this, the core team subsequently switched from using .rbenv-version to .ruby-version. So if you see me referring to both filenames and get confused, just know that they had the same purpose.

Finding the right git SHA

In order to find this PR, we need to know its SHA number ("SHA" stands for "Simple Hashing Algorithm"). The SHA is a unique identifier that git uses to refer to a specific commit. Once we have this, we can plug it into Github's search bar, pull up the corresponding PR and any associated Github Issues, and review any relevant discussions (which might give us more context).

Note that this is not a git tutorial, and that git knowledge is a prerequisite for moving forward. If you're not yet familiar with git, the official git docs contain a great tutorial here.

Attempting to run git blame on the shim file

Normally we could just use git blame to get this SHA directly from the line of code in our file. But if we try that here, we see the following:

~/.rbenv (master)  $ git blame `which bundle`          
fatal: no such path 'shims/bundle' in HEAD
~/.rbenv (master)  $

The error no such path 'shims/bundle' in HEAD appears because the shim directory ~/.rbenv/shims is included in RBENV's .gitignore file, meaning the shims are not stored in a git repo (and hence don't have their own SHA). We can confirm this by looking at RBENV's .gitignore file. If we run the following in our terminal...

$ vim ~/.rbenv/.gitignore

...we'll see the following file contents:

/plugins
/shims
/version
/versions
/sources
/cache
/libexec/*.dylib
/src/Makefile
/src/*.o
/gems

That /shims folder on line 2 is the parent directory for our bundle command. RBENV doesn't track the contents of the shims/ directory because each user's machine will have a different set of Ruby gems installed, meaning the filenames inside each user's shims/ directory will be different.

Trying again- looking for where the code lives

However, we know that the shims all have the same exact code, and also that new shim files are generated every time we install a new gem. Given this knowledge, I'd bet that there's a "shim factory" somewhere in the RBENV codebase, which auto-generates a new file whenever a new gem is installed.

One strategy to find this shim factory is to search the RBENV codebase for an arbitrary piece of code from the shim file. But first we need to pick which line of code to search for. I pick a line which I suspect will not be too common in the codebase, giving us a high signal-to-noise ratio in our search results. Then I use the ag tool to find its location:

$ cd ~/.rbenv/

$ ag 'program" = ruby'

libexec/rbenv-rehash
65:if [ "\$program" = ruby ]; then

$

Looks like there is only one search result, in a file named libexec/rbenv-rehash, and it looks quite promising:

53 # The prototype shim file is a script that re-execs itself, passing
54 # its filename and any arguments to `rbenv exec`. This file is
55 # hard-linked for every executable and then removed. The linking
56 # technique is fast, uses less disk space than unique files, and also
57 # serves as a locking mechanism.
58 create_prototype_shim() {
59   cat > "$PROTOTYPE_SHIM_PATH" <<\SH
60 #!/usr/bin/env bash
61 set -e
62 [ -n "\$RBENV_DEBUG" ] && set -x
63     
64 program="\${0##*/}"
65 if [ "\$program" = ruby ]; then
66   for arg; do
67     case "\$arg" in
68     -e* | -- ) break ;;
69     */* )
70       if [ -f "\$arg" ]; then
71         export RBENV_DIR="\${arg%/*}"
72         break
73       fi
74       ;;
75     esac
76   done
77 fi
79 export RBENV_ROOT="$RBENV_ROOT"
80 exec "$(rbenv_path)" exec "\$program" "\$@"
81 SH
82   chmod +x "$PROTOTYPE_SHIM_PATH"
83 }

The code we searched for lives inside a function called create_prototype_shim(). That sounds a lot like the "shim factory" we hypothesized!

We now have a pretty confident guess about where in the RBENV codebase the if-block comes from. Next let's look at the git history for that file.

Running git blame on the correct file

I copy the filepath for rbenv-rehash and run git blame on it (docs on this command here):

$ git blame libexec/rbenv-rehash

You should see something like this:

$ git blame libexec/rbenv-rehash                  
6938692c libexec/rbenv-rehash (Andreas Johansson 2011-08-12 11:33:45 +0200   1) #!/usr/bin/env bash
37eca782 libexec/rbenv-rehash (Sam Stephenson    2012-12-29 22:05:04 -0600   2) # Summary: Rehash rbenv shims (run this after installing executables)
4c19dc22 libexec/rbenv-rehash (Sam Stephenson    2012-12-29 12:06:20 -0600   3) 
6938692c libexec/rbenv-rehash (Andreas Johansson 2011-08-12 11:33:45 +0200   4) set -e
0632325a libexec/rbenv-rehash (Sam Stephenson    2011-09-12 10:11:59 -0500   5) [ -n "$RBENV_DEBUG" ] && set -x
...

And if you keep scrolling down, eventually you should see our create_prototype_shim function:

...
fffb29d6 libexec/rbenv-rehash (Sam Stephenson    2011-08-03 22:57:27 -0500  58) create_prototype_shim() {
dd8a005c libexec/rbenv-rehash (Sam Stephenson    2011-08-15 01:16:13 -0500  59)   cat > "$PROTOTYPE_SHIM_PATH" <<\SH
6938692c libexec/rbenv-rehash (Andreas Johansson 2011-08-12 11:33:45 +0200  60) #!/usr/bin/env bash
6938692c libexec/rbenv-rehash (Andreas Johansson 2011-08-12 11:33:45 +0200  61) set -e
283e67b5 libexec/rbenv-rehash (Sam Stephenson    2012-12-27 13:41:55 -0600  62) [ -n "\$RBENV_DEBUG" ] && set -x
...

If you don't, make sure the RBENV repository you're in is pointing to git SHA # c4395e58201966d9f90c12bd6b7342e389e7a4cb when you run the above command.

If you've never run git blame before, you might think this output is quite hard to parse. Let's learn what it all means.

Interpreting the results of git blame

Using line 64 as an example, we see the following:

283e67b5 libexec/rbenv-rehash (Sam Stephenson    2012-12-27 13:41:55 -0600  64) program="\${0##*/}"
  • "283e67b5"- this is the first 8 characters of the SHA that we're looking for. This is what we'll plug into Github's search box.
  • "libexec/rbenv-rehash"- this is the filename we're looking at, in the form of "path/to/filename" relative to our current directory.
  • "(Sam Stephenson"- this is the name of the person who authored the commit. This is where the command git blame gets its name- we want to know "who to blame" (or praise, as the case may be).
  • "2012-12-27 13:41:55 -0600"- this is the date that the code was committed to the repository.
  • "64)"- this is the line number of the code in the file itself.
  • "program="\${0##*/}""- finally, this is the line of code itself.

As I mentioned, what we care about is the left-most column. It contains the first 8 characters of the commit's unique identifier (also called a SHA) which introduced each line of code. This isn't the full SHA, just a snippet, but it's almost certainly long enough to make any collisions with other commits unlikely.

Notice also that the SHA ("283e67b5") is the same for the entire if-block. That's lucky for us- it means that this code was all added to the repo at the same time, and gives me more confidence that this is the SHA we want. If there were many different SHAs, each with different commit dates, it would be more of a slog to search each one until we found the PR we want.

Reading the SHA's history on Github

Now that we have our SHA, I open my web browser and go to Github, where I paste the SHA value I copied from git blame into the search bar on the top-left and select "In this repository" (click the images to enlarge in a new window):

Searching for SHA # 283e67b5 on Github's homepage.

Hitting Enter and moving to the search results page, we see Github says "we couldn't find any code"...

No code results found for SHA # 283e67b5 on Github's search page.

...but that message is irrelevant for us. We're not looking for code; we're looking for a PR. And on the left-hand side, we can see that Github did find one issue and one commit containing this SHA:

Close-up of Github search results, showing one commit and one pull request which match the SHA we searched for.

I right click on each section to open them in new tabs.

Reading the Github commit

First, the commit results:

The git commit which matches the SHA we searched for.

Reconstructing the commit message (which was truncated due to its length), we can see at the top that the commit message for this commit was:

When the ruby shim is invoked with a script, set RBENV_DIR to the script's dirname

This sounds similar to our hypothesis.

Reading the Github Issue

Let's also check the issue link:

The Github issue which matches the SHA we searched for.

The description says:

This branch adjusts the behavior of the ruby shim, when invoked with the path to a Ruby script as an argument, to set RBENV_DIR to the directory of the given script. It should, in effect, remove the need for the ruby-local-exec shebang line.

While I don't yet understand the reference to "ruby-local-exec", the rest of it sounds pretty close to what we hypothesized.

Following the Github conversation history

Before closing the browser tab, I notice the following at the end of the PR:

See previous discussion at #298

Out of curiosity I read through that PR. Among other things, it contains a conversation which stands out to me:

A comment from Mislav Marohnić explaining why he would consider it surprising behavior if RBENV used the Ruby version of a local directory instead of the current directory, if those two directories were different.

Mislav (a member of the RBENV core team) says that he would consider it to be surprising behavior if:

  • he was in one directory,
  • he ran a Ruby script in a separate directory, and
  • the Ruby script used the Ruby version of the 2nd directory.

Replying to Mislav, another contributor (Jeremy) disagrees that this would be surprising behavior, saying that adding a .rbenv-version file to a project is like declaring a Ruby dependency.

A reply to Mislav's comment from Jeremy, saying that adding a .rbenv-version file to a project is like declaring a dependency for that project, therefore making it unsurprising behavior for RBENV to use that project's declared Ruby version.

Finally, Sam Stephenson (the lead developer of the RBENV project) chimes in to specify what the order of precedence needs to be when checking for a Ruby version:

Sam Stephenson's comment on the order of operations that RBENV should use for deriving a project's Ruby version.
  • The shell's version (i.e. if a user has set "RBENV_VERSION" directly in their shell)
  • The version inside the script's local directory.
  • The version inside the user's current directory.
  • The user's global Ruby version (set in "~/.rbenv/version" or by the "rbenv version " command).

I get the impression that, at the time this conversation took place, this was not yet how RBENV worked in practice. If that's true, this could represent another reason why the if-block was an improvement over the previous version of the shim. Let's try to reproduce this behavior, for educational purposes.

Testing our hypothesis about the if-block

My plan is to create two directories with different local Ruby versions, as well as a 3rd Ruby version set globally (i.e. for all other directories except for these two new ones) to avoid conflicts with the versions in these 2 directories. Then I'll test which version of Ruby is picked up by RBENV inside each directory.

Making sure we're at the right starting point

First, I make sure that the version of RBENV that I'm running (i.e. the SHA that I'm pointing to in my ~/.rbenv directory) matches the last of the commits in the PR which added the if-block:

The list of commits for the PR which introduced the 'if'-block in the shim code.  The specific commit that we want to roll back to is highlighted.

Above we can see that the last of the SHAs in the PR which introduced the if-block is 339e331. That's the one we want.

~/.rbenv (impostorsguides)  $ git co 339e331f1dcdbbe3659981968e081492817023ed   
Note: switching to '339e331f1dcdbbe3659981968e081492817023ed'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c 

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 339e331 Ensure outdated shims are removed first when rehashing

$ 

Here we navigate into the ~/.rbenv directory, and run git checkout 339e331 to roll back our RBENV installation to the commit we want. I then check out a new git branch with a descriptive name so that I can quickly hop back to this version of the code if I need to:

~/.rbenv (v0.4.0~26^2)  $ git co -b just-after-if-block
Switched to a new branch 'just-after-if-block'
~/.rbenv (just-after-if-block)  

Re-generating the shims using our new code

Next, because we're now pointing to a much older commit, I suspect the shim code may have changed. So I open up a new terminal tab, so as to re-trigger the RBENV shell integration.

Next, I delete and re-create all the shims in RBENV's shims/ directory, to make sure my shim code matches my current version of RBENV:

$ rm -rf shims/*
zsh: sure you want to delete all 37 files in /Users/richiethomas/.rbenv/shims [yn]? y
~/.rbenv (just-after-if-block)  $ rbenv rehash
~/.rbenv (just-after-if-block)  $

I verify that the shim for the ruby command looks the way I expect:

~/.rbenv (just-after-if-block)  $ cat `which ruby`
#!/usr/bin/env bash
set -e
[ -n "$RBENV_DEBUG" ] && set -x

program="${0##*/}"
if [ "$program" = ruby ]; then
  for arg; do
    case "$arg" in
    -e* | -- ) break ;;
    */* )
      if [ -f "$arg" ]; then
        export RBENV_DIR="${arg%/*}"
        break
      fi
      ;;
    esac
  done
fi

export RBENV_ROOT="/Users/richiethomas/.rbenv"
exec rbenv exec "$program" "$@"
~/.rbenv (just-after-if-block) $ 

The only difference between our original shim and this new shim is that the exec statements at the bottom are different. We see exec rbenv exec instead of exec "/Users/richiethomas/.rbenv/libexec/rbenv" exec. This is because we've rolled back to an earlier version of RBENV, which generated a different prototype shim. The important thing is that we still see the if-block, and that its code is the same as in our original shim.

Setting up 3 different Ruby versions

Next, I navigate into a directory which I know doesn't have an RBENV version file in it. In the RBENV version that we've rolled back to, the file name is .rbenv-version, i.e. at this point in time the core team hadn't yet switched to using .ruby-version.

Once I'm in my new directory, I set a global Ruby version with a number which I know is already installed:

$ cd ~/Desktop/Workspace/scratch 
~/Desktop/Workspace/scratch ()  $ rbenv local
rbenv: no local version configured for this directory
~/Desktop/Workspace/scratch ()  $ rbenv global
3.2.2
~/Desktop/Workspace/scratch ()  $ rbenv local 3.1.0
~/Desktop/Workspace/scratch ()  $ rbenv local
3.1.0
~/Desktop/Workspace/scratch ()  $

Setting a "global" version number will make this the default Ruby version on my machine, but this default can be over-ridden for specific project directories. This is what we'll do next. I do this because I want to avoid a situation where my .rbenv-version file contains the same version number as the global version number, which could make it confusing as to what the source of the version number was.

Next, I make two project directories, named foo/ and bar/ respectively, with each containing a .rbenv-version file with a version number that is different from my global Ruby version. My foo/ directory contains Ruby version 3.0.0:

~/Desktop/Workspace/scratch ()  $ mkdir foo
~/Desktop/Workspace/scratch ()  $ echo "3.0.0" > foo/.rbenv-version
~/Desktop/Workspace/scratch ()  $ 

And my bar/ directory contains Ruby version 2.7.5:

~/Desktop/Workspace/scratch ()  $ mkdir bar
~/Desktop/Workspace/scratch ()  $ echo 2.7.5 > bar/.rbenv-version
~/Desktop/Workspace/scratch ()  $ 

The > symbol after the echo command means that, instead of printing my string to the screen, we're sending it to a file named .rbenv-version inside the foo/ and bar/ directories. If this file doesn't yet exist (which it doesn't, because we just created those directories), then we create it. This is called redirection, and we'll cover it in more detail in a future section.

Printing the Ruby version

I then create two files named foo/foo.rb and bar/bar.rb. The 2 files do the same thing- they simply print the version of Ruby that the interpreter is using:

~/Desktop/Workspace/scratch ()  $ echo "puts RUBY_VERSION" > foo/foo.rb
~/Desktop/Workspace/scratch ()  $ echo "puts RUBY_VERSION" > bar/bar.rb
~/Desktop/Workspace/scratch ()  $ 

I navigate into bar/ and run bar.rb:

$ cd bar 
~/Desktop/Workspace/scratch/bar ()  $ ruby bar.rb 
2.7.5
~/Desktop/Workspace/scratch/bar ()  $ 

Then, while still inside bar, I run foo/foo.rb:

~/Desktop/Workspace/scratch/bar ()  $ ruby ../foo/foo.rb 
3.0.0
~/Desktop/Workspace/scratch/bar ()  $ 

This is what I'd expect based on reading the core team's PR conversation: each file uses the Ruby version pinned by its respective .rbenv-version file, regardless of where I am when I run it.

Repeating the process, before the if-block was added

Next, I find the SHA of the version of the RBENV code just before the if-block was introduced:

The list of commits for the PR which introduced the 'if'-block in the shim code.  The specific commit that we want to roll back to is highlighted.

I then check out that SHA in my repo, giving this another descriptive branch name:

~/.rbenv (just-after-if-block)  $ git co -f 6c1fb9ffd062ff04607d2e0f486067eaf6e48d1e~
Note: switching to '6c1fb9ffd062ff04607d2e0f486067eaf6e48d1e~'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c 

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at c3fe192 use ruby-build
~/.rbenv (v0.4.0~29)  $ git co -b just-before-if-block                     
Switched to a new branch 'just-before-if-block'
~/.rbenv (just-before-if-block)  $ 

Once again, I delete and re-build my shims

$ rm -rf shims/*
zsh: sure you want to delete all 37 files in /Users/richiethomas/.rbenv/shims [yn]? y

~/.rbenv (just-before-if-block)  $ rbenv rehash
~/.rbenv (just-before-if-block)  $ 

I verify that my ruby shim no longer has the if-block:

~/.rbenv (just-before-if-block)  $ cat `which ruby`
#!/usr/bin/env bash
set -e
export RBENV_ROOT="/Users/richiethomas/.rbenv"
exec rbenv exec "${0##*/}" "$@"
~/.rbenv (just-before-if-block)  $ 

We see the if-block is gone. That's what we want.

Now, back in my bar/ directory, I re-run both bar.rb and ../foo/foo.rb:

~/Desktop/Workspace/scratch/bar ()  $ ruby bar.rb 
2.7.5
~/Desktop/Workspace/scratch/bar ()  $ ruby ../foo/foo.rb 
2.7.5
~/Desktop/Workspace/scratch/bar ()  $ 

With the if-block removed, we now see that the Ruby version for foo does not reflect the version number specified in its .rbenv-version file if we run foo.rb from within the bar/ directory.

But if we navigate from bar/ into its sibling foo/ and run foo.rb, it changes back to the version we expect, 3.0.0:

~/Desktop/Workspace/scratch/bar ()  $ cd ../foo
~/Desktop/Workspace/scratch/foo ()  $ ruby foo.rb   
3.0.0
~/Desktop/Workspace/scratch/foo ()  $ 

Conclusion: our hypothesis was correct

So we can see that one of the things that the if-block does is help pin the Ruby version of a file we run based on the .rbenv-version file in the same directory. Judging by the conversation in the PR, this seems to be what the core team intended. Speaking for myself, it's also what I as a user would expect the behavior to be, so I can understand why they did what they did.

Before moving on, I make sure to clean up the mess I made:

~/Desktop/Workspace/scratch/foo ()  $ cd ~/.rbenv 
~/.rbenv (just-before-if-block)  $ git co impostorsguides
Switched to branch 'impostorsguides'
~/.rbenv (impostorsguides)  $ git branch -D just-before-if-block just-after-if-block
Deleted branch just-before-if-block (was c3fe192).
Deleted branch just-after-if-block (was 339e331).
~/.rbenv (impostorsguides)  $ 

Lastly, I delete my old shims and run rbenv rehash to re-build them using my desired RBENV version. I then verify that those shim contain the if-block and otherwise look the way we expect:

~/.rbenv (impostorsguides)  $ rm -rf shims/*
zsh: sure you want to delete all 37 files in /Users/richiethomas/.rbenv/shims [yn]? y

~/.rbenv (impostorsguides)  $ rbenv rehash

~/.rbenv (impostorsguides)  $ cat `which ruby`

#!/usr/bin/env bash
set -e
[ -n "$RBENV_DEBUG" ] && set -x

program="${0##*/}"
if [ "$program" = ruby ]; then
  for arg; do
    case "$arg" in
    -e* | -- ) break ;;
    */* )
      if [ -f "$arg" ]; then
        export RBENV_DIR="${arg%/*}"
        break
      fi
      ;;
    esac
  done
fi

export RBENV_ROOT="/Users/richiethomas/.rbenv"
exec "/Users/richiethomas/.rbenv/bin/rbenv" exec "$program" "$@"
~/.rbenv (impostorsguides)  $ 

Now everything looks as it should here.

Takeaways

At the risk of getting on top of my soapbox, I hope that one of your take-aways from reading the above is to make sure your team's PRs contain detailed context. If the RBENV core team was not dilligent and thorough in its discussion of the pros and cons of the approach they ended up taking, none of the above learning would have been possible, and we would have been left in the dark about their intentions. In a production environment serving a large user base, the consequences of this could be significant.

But it's not all bad news. If teams maintain a policy of leaving detailed remarks on PRs and Github issues, the result is that they empower their members to answer their own questions, instead of needing to reach out to others for answers (which may or may not be possible, due to coworkers taking PTO, leaving the company, taking sick days, etc.). This results in fewer interruptions, better-informed decisions, and faster feature delivery.

On that note, thanks for joining me on this deep-dive into the history of the RBENV shim. I hope this was somewhat useful to you.

Photo Attribution

Title of Photo: Useless gate on a path by the railway.

Description: "The field boundary has been removed but the gate has been left standing on its own."

Author: Ian Calderwood

Source: Geograph

License: CC BY-SA 2.0 DEED Attribution-ShareAlike 2.0 Generic