---
title: ".git/safe"
teaser: 'How to use .git/safe to trust the bin/ directory in your git repo.

  '
tags: shell,git,rails
author:
- Ian Zabel
- Mike Burns
published_on: 2019-07-29
---

Some years ago, vim expert Tim Pope tweeted [a clever suggestion] for using
`bin/`:

> `PATH=".git/safe/../../bin:$PATH"` and do `mkdir .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.

[a clever suggestion]: https://twitter.com/tpope/status/165631968996900865?lang=en

## 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](https://thoughtbot.com/blog/use-bundlers-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`][bundle-exec-blog-post] 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.

[gitsh]: https://github.com/thoughtbot/gitsh
[bundle-exec-blog-post]: https://thoughtbot.com/blog/but-i-dont-want-to-bundle-exec

## Where do I start?

Well, you could add the relative `bin` directory to your `$PATH`:

```sh
% 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:

```sh
% 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`:

```sh
% mkdir -p .git/safe
```

## In practice

``` shell
# 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](https://github.com/thoughtbot/dotfiles/blob/master/bin/git-trust-bin),
you'll find that you already have a handy way of trusting your project. You can
just run:

```shell
% 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](https://github.com/thoughtbot/dotfiles/pull/533).

## Built into thoughtbot's Rails template, Suspenders

If you use [thoughtbot's Suspenders](https://github.com/thoughtbot/suspenders)
as a template to create a new Rails project, you get a [`bin/setup`
script](https://github.com/thoughtbot/suspenders/blob/master/templates/bin_setup)
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](https://github.com/thorncp/dotfiles/blob/dea9c983/vimrc#L232-L234),
you'll find an example of trusting the git repo to maintain a `vimrc.local` and
reading that in from a `vimrc`.

```vim
if filereadable(".git/safe/../../vimrc.local")
  source .git/safe/../../vimrc.local
endif
```
