我想将当前的 git 哈希放入我的提示中;但我最初的方法有点滞后:
psvar[1]="$(git log -n1 --pretty='format: %h' 2>/dev/null)"
(包括$PROMPT
使其%1v
可见)
我尝试了vcs_info
插件,但效果也不太好。所以我最终写了自己的函数:
function githead() {
local commondir ref hash _
local gitdir="${1:a}"
until [[ -e "$gitdir/.git" ]]; do
local updir="${gitdir%/*}"
[[ "$updir" == "$gitdir" ]] && return 1
gitdir="$updir"
done
gitdir="$gitdir/.git"
[[ -f "$gitdir" ]] && read _ gitdir < "$gitdir"
read _ ref < "$gitdir/HEAD"
local commondir="$gitdir/commondir"
[[ -e "$commondir" ]] && gitdir="$gitdir/$(<$commondir)"
ref="$gitdir/$ref"
read hash <"$ref"
print -r "${hash::12}"
return 0
}
它确实更快,但注定会很脆弱。特别是,我必须读取的几个文件看起来可能包含多行内容,而且不一定将我想要的行放在顶部。
有没有一种快速的方法可以从 git 获取当前哈希,并且比我手写的更加强大?
扩展 refs 的低级工具是
git rev-parse
:普通引用每次仅指向一个提交。只有极少数例外,例如 FETCH_HEAD,但无论如何这些都不能成为 HEAD 的目标。
然而,问题不在于多行,而在于 ref 可能被打包——它们不能保证作为离散文件存在于中
.git/refs/
;它们可能只是其中的一行.git/packed-refs
(或者甚至是最新“git”版本中其他一些新引入的“ref 数据库”)。我在自己的提示符中使用的 bash 实现- 我从未发现“当前提交”指示有用,因此它准确显示 HEAD 指向的内容,并且根本不尝试取消引用它。(如果它向我显示原始提交 ID,那么我知道我处于分离的 HEAD 上。)
考虑到 @grawity 提出的观点,我保留了手动实现,但修复了几个错误并添加了后备:
在这里,我特意检查了 的内容,
HEAD
以确定它是否有ref:
前缀,或者它是否是原始哈希(分离的头部情况)。我还使用$(<file)
文件不可读时设置的错误结果,而不是事先执行单独的测试(因此将所有内容包装在 中{} 2>/dev/null
)。虽然我确实编写并测试了一个读取
packed-refs
文件的函数,但我认为这毫无意义,因为如果它存在,可能是因为它很大,而我的实现可能比直接调用 git 更慢。所以我改为调用 git。如果哈希值非空,则最后一行会在前面添加一个空格,这样就不会在空字符串的两边都出现空格。