How to get the path of a file relative to the Git repository root?

I would like to improve on @gmatht's answer by making it work in an corner-case, by resolving the git root differently:

git-absolute-path () {
    fullpath=$([[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}")
    gitroot="$(echo $(cd $(git rev-parse --show-cdup) .; pwd))" || return 1
    [[ "$fullpath" =~ "$gitroot" ]] && echo "${fullpath/$gitroot\//}"
}

The corner-case I'm referring to is when your git repo is in /tmp and you're on Windows. /tmp seems to be a special case: it refers to your Windows user's temp folder i.e. C:/Users/<user>/AppData/Local/Temp. (Not sure "how" it refers to that, it doesn't appear to be a symlink. Like I said, a special case). In any case, fullpath can be like /tmp/your-temp-repo but gitroot can be like C:/Users/<user>/AppData/Local/Temp/your-temp-repo but then they're not equal and git-absolute-path returns nothing incorrectly.


Pasting the following into your bash terminal will work, regardless of whether "test.c" currently exists or not. You can copy the git-absolute-path function into your .bashrc file for future convenience.

git-absolute-path () {
    fullpath=$([[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}")
    gitroot="$(git rev-parse --show-toplevel)" || return 1
    [[ "$fullpath" =~ "$gitroot" ]] && echo "${fullpath/$gitroot\//}"
}

git-absolute-path test.c

Use git ls-files:

$ cd lib
$ git ls-files --full-name test.c
lib/test.c

This only works for files that have been committed into the repo, but it's better than nothing.

Tags:

Git

Path