The letter A styled as Alchemists logo. lchemists

Putin's War on Ukraine - Watch President Zelenskyy's speech and help Ukraine fight against the senseless cruelty of a dictator!

Published December 14, 2019 Updated May 10, 2020

Git Safe

Demonstrates the Git Safe technique for having local access to your bin scripts without having to type the full path.


# Hello and welcome to the Alchemists Screencasts!
# Today, we'll look at using the Git Safe technique.

# You might have originally read of this via the following article:
# Let's take a closer look by examining a simple project structure:


# Notice the `bin/example` script:

cat bin/example

# Not much to it as the last line prints it has run:


# It would be nice if we could run the script without the relative path.
# With the Git Safe technique, we can accomplish that.
# The basic idea is to *dynamically* add the `bin` folder to your path.
# More importantly, the `bin` path is *only* loaded for the current project.
# This technique is so useful that I use a shell function for this:

cype gafe

# The `gafe` function name is comprised of the following: "(g)it" + "s(afe)" = "gafe". 😉
# The meat of the function is on Line 5 and 7:

cype gafe | rg --color never --after-context 0 "mkdir"

# The above creates the "safe" directory within the ".git" folder.
# Next we need to ensure the `.git/safe` directory is added to your path:

cype gafe | rg --color never --after-context 0 "exec"

# This is important so you can *immediately* leverage the path in your current shell.
# There is only one more step needed to make this all work.
# You must add this line to your `.bashrc` script:
# `export PATH=".git/safe/../../bin:$PATH"`
# Here is my setup:

cat "$HOME/.bashrc" | tail -1

# Notice how `.git/safe/../../bin` is prepended to the path.
# This is where the magic happens.
# This ensures the `bin` folder (two directories up) is loaded on your path. 🎉
# This condition *only* works if the current project has a `.git/safe` directory.
# To recap, when we run:


# This works. However, if if we run:


# That fails accordingly.
# So let's make this project safe:


# To confirm, we can see the `.git/safe` directory now exists (last directory):

ls -alhT .git

# Now we can run the script without the relative path:


# Much better!
# When leaving the project, running `example` will no longer work:

cd ..

# When we return to the project, functionality returns:

cd demo

# To make the project no longer *safe*, we can remove the Git Safe directory:

rm -rf .git/safe

# We are back where we started because the `bin` directory is no longer safe.
# The caveat is you should only mark projects safe which you *trust*.
# That said, this makes working in *safe/trusted* projects a lot easier.
# For example, in Ruby (via Bundler binstubs), being able to type the following is nice:

# rspec
# rake
# rubocop
# ...etc...

# For fans of direnv (, there is an alternative approach.
# First, you'll want to install direnv via Homebrew:

brew install direnv

# Now we can leverage direnv by configuring and enabling it:

printf "%s\n" "PATH_add bin" > .envrc
direnv allow

# Finally, we can execute our script, leveraging direnv:


# As before, with Git Safe, leaving the project disables script access:

cd ..

# Both Git Safe and direnv are powerful tools for improving your workflow.
# Git Safe is handy when you need personal customization or don't need the direnv dependency.
# direnv is handy when you need a custom environment and/or sharing team functionality.

# Enjoy!
# ☿ 🜔 🜍 🜂 🜃 🜁 🜄