如何获取文件相对于Git仓库根目录的路径?

39

例子:

$ cd lib
$ git absolute-path test.c # how to do this?
lib/test.c

10
“绝对路径”和“相对于仓库”的说法似乎相互矛盾? - WiseOldDuck
4个回答

40
使用 git ls-files 命令:
$ cd lib
$ git ls-files --full-name test.c
lib/test.c

这只适用于已提交到存储库中的文件,但总比没有好。


我必须使用通配符,否则除非文件在存储库的根目录中,否则找不到该文件。使用 $ git ls-files --full-name *test.c。 - Pedro García Medina
@PedroGarcíaMedina 我发布的两个命令都期望 test.c 是相对于当前工作目录的路径。所以,当你已经知道文件在哪里,但是想要将路径转换为相对于存储库根目录的“绝对”路径时,可以使用这些命令。如果你正在尝试搜索 repo 中是否存在名为 test.c 的文件,我建议运行cd "$(git rev-parse --show-toplevel)"; git ls-files --full-name '*/test.c' 'test.c'。注意引号,以防止 shell 插值星号。 - Jo Liss

7
将以下内容粘贴到bash终端中即可运行,无论"test.c"是否存在。您可以将git-absolute-path函数复制到您的.bashrc文件中以便将来使用。
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

1
Mac OS X的“readlink”没有-f选项(我推测*BSD也是如此)。有什么便携式的方法可以解决这个问题吗? - TomOnTime

3
为了获取相对于Git根目录的当前目录路径,我最终采用了如下方法:
if gitroot=$(git rev-parse --show-toplevel 2>/dev/null); then
    directory=$(realpath --relative-to="$gitroot" .)
fi

(我假设您使用的是Bash,但我不知道这有多可移植。)

1

我希望在@gmatht的答案基础上进行改进,使其适用于一些边缘情况,通过不同的方式解析git根目录:

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\//}"
}

我所指的边缘情况是当你的git仓库在/tmp目录下并且你正在使用Windows系统时。/tmp似乎是一个特殊情况:它指的是你Windows用户的临时文件夹,即C:/Users//AppData/Local/Temp。(不确定它是如何指向那里的,它似乎不是符号链接。就像我说的,这是一个特殊情况)。无论如何,fullpath可能是/tmp/your-temp-repo,但gitroot可能是C:/Users//AppData/Local/Temp/your-temp-repo,但它们不相等,因此git-absolute-path会错误地返回空值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接