Some years ago, vim expert Tim Pope tweeted a clever suggestion for using
bin/
:
PATH=".git/safe/../../bin:$PATH"
and domkdir .git/safe
in the root of repositories that you trust.
When we originally read that, we liked the suggestion so much that we incorporated it in our workflow and into some of our tools. Read on to know more.
Why would I want to do this?
If you’re a Rails developer you’ve definitely seen a bin/
directory in your
project root. It contains programs like bin/rails
and bin/rake
and
bin/rspec
. You may use these commands instead of bundle exec <command>
to
ensure you’re getting the correct versions of gem dependencies. bin/rails
and
the other binstubs in the
bin/
directory eliminate the need for bundle exec
. But, it’s nicer to be
able to just type rails
instead of bin/rails
or bundle exec rails
. There
are a number of workarounds described in the But I Don’t Want to bundle
exec
blog post.
Even if you’re not a Rails dev, other projects might have a handy bin/
directory with helper programs for developing the app; for example, the gitsh
project has a bin/gitsh
helper program that only works while developing the
project.
Where do I start?
Well, you could add the relative bin
directory to your $PATH
:
% PATH="bin:$PATH"
The downside is that this means that anywhere you cd
, ./bin
will be in your
path. This may be fine most of the time, but devs who navigate around other
people’s codebases might not want to find a bin/ls
lurking somewhere under
node_modules
, waiting for you to cd
in while investigating and debugging
some third-party library.
The trick described in Tim’s tweet is to add bin
to your $PATH
through a
directory you control, like so:
% PATH=".git/safe/../../bin:$PATH"
Whenever we vet and trust a project’s directory and their developers, we can add
that project’s bin
directory to our $PATH
:
% mkdir -p .git/safe
In practice
# Initial configuration
% PATH=".git/safe/../../bin:$PATH"
# without having trusted a project, we fall
# back to the default `rspec` in our ruby
# version manager (asdf in this case)
% cd work/project_with_bin_dir/
% which rspec
/Users/home/.asdf/shims/rspec
% mkdir -p .git/safe # we decide we trust this repo
% which rspec
.git/safe/../../bin/rspec # great! now we can just run `rspec`
% rspec # no need to `bundle exec rspec`
Built into thoughtbot’s dotfiles
If you’re using thoughtbot’s dotfiles, you’ll find that you already have a handy way of trusting your project. You can just run:
% git trust-bin
This will create the .git/safe
directory for you. You can find some more
information about this script in the pull-request that created
it.
Built into thoughtbot’s Rails template, Suspenders
If you use thoughtbot’s Suspenders
as a template to create a new Rails project, you get a bin/setup
script
that can be used to bootstrap the project onto new machines.
This script checks to see if you have .git/safe
in your path. If you do,
you’ll get a helpful message reminding you to create the .git/safe
directory
to trust the repo.
-> When you trust this repo, remember to run: mkdir -p .git/safe
Other uses for .git/safe
While we’re talking about easily using the bin/
directory here, this technique
is also useful for files that are not in bin
. In Chris Thorn’s
dotfiles,
you’ll find an example of trusting the git repo to maintain a vimrc.local
and
reading that in from a vimrc
.
if filereadable(".git/safe/../../vimrc.local")
source .git/safe/../../vimrc.local
endif