On , I learnt ...

Git aliases that run an external command are run from the repository root

Verify this by creating an alias in ~/.gitconfig like so:

pwd = "!f() { pwd; }; f"

and you’ll find that, no matter where you call git pwd from, it always prints the repository root directory.

This is annoying for git diff --relative aliases where it’s desirable to have the printed filepaths relative to the current directory.

For example, until five minutes ago I had this alias for printing all files touched in a pull request:

prfiles = "!f() { git diff --relative --name-only origin/master...HEAD; }; f"

but this would print the path from the repository root, meaning you couldn’t pipe the output to a command unless your current directory was the repository root.

The solution is to use the $GIT_PREFIX environment variable which contains the directory where the alias was invoked. So my prfiles alias is now:

prfiles = "!f() { cd ${GIT_PREFIX:-./}; git diff --relative --name-only origin/master...HEAD; }; f"

Note, we define a default value of ./ as $GIT_PREFIX isn’t set when the alias is invoked from the repository root.

Now I can run things like:

$ git prfiles | xargs rg -l "foo" | xargs -o vim

to edit all files from my pull request that contain “foo”.

The $GIT_PREFIX variable has been available since v1.7.6). It’s a little hard to find as it isn’t mentioned in the current online docs on aliases but is documented in the man pages (try man -K GIT_PREFIX).