测试git目录和git分支的正确而快速的方法?

And*_*ero 7 shell git prompt fish

在尝试设置我的新鱼壳提示时,我最终测试了获取分支名称的方法,并测试了我是否在 git 存储库上。我发现(1) git rev-parse --abbrev-ref HEAD , (2) git symbolic-ref HEAD | sed 's/refs\/heads\///'(3) git describe --contains --all HEAD可以很好地解决问题。

我很好奇,因为我喜欢(1)的简单性,但是在一个新的和未受影响的(只是git inited)存储库上,它给了我一个“致命的:”错误,而(2)按预期工作,也就是说,给了我一个默认作为输出。问题是,即使出现“致命:”错误,返回码也是 0。这是预期的行为吗?

为了测试我是否在 git 存储库中,我最终只是测试当前目录是否有一个“.git”文件夹:test -d ".git". 基本的解决方案,但它有效,而且似乎比使用任何 git 命令都要快。

所以,我的问题是:

  1. 那个“fatal:”和(1)不应该返回一个不同于 0 的退出代码吗?如果确实是一个错误,因为我不知道 git 人们如何标准化他们的返回代码,我应该在哪里报告它?
  2. 我知道如果我重定向(1)^ /dev/null(对于那些不知道的人,^与 相同2>),我不会得到错误,但它会说HEAD而不是 master,但如果我cat .git/HEAD,我得到:ref: refs/heads/master。它真的应该说什么?随着master我只是无知和挑剔,因为它应该不是说HEAD?我的意思是在刚刚git inited 存储库的情况下。
  3. 在您寻求获得良好提示的过程中,您是否真的对任何可能的解决方案进行了基准测试?

这是我用来基准测试的代码(用于鱼):

set -l before (date +%s%N)
git rev-parse --abbrev-ref HEAD
set -l after (date +%s%N)
set -l elapsed_time (expr $after - $before)
echo $elapsed_time
Run Code Online (Sandbox Code Playgroud)

提前致谢!

PS:这些工具是最新的 GNU 版本,我的意思是seddateexpr。如果信息过多或没有任何意义,我很抱歉。忍受我。谢谢!

编辑:正如有人在答案中正确猜测的那样,整个错误是:

fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
Run Code Online (Sandbox Code Playgroud)

Chr*_*her 4

没有完全回答您的问题,但可能不仅仅是评论:

  1. 根据您答案中的其他评论,我认为您看到的错误是fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.因为您正在一个全新的 git 存储库上进行这些测试,而该存储库没有提交工作。这不仅不是一个真正公平的测试(根据定义,在较大的存储库上,您的性能会更差),而且几乎在所有方面都是一种边缘情况。例如,按惯例.git/HEAD显示。ref: refs/heads/master抛出错误是因为HEAD不明确。您没有历史记录,因此传递给的任何值都rev-parse将被视为相同。另外,这对我来说并不退出 0:

    $ git init /tmp/test && cd /tmp/test
    $ git rev-parse --abbrev-ref HEAD
    $ echo $?
    128
    
    Run Code Online (Sandbox Code Playgroud)

    总之,不要担心这个错误。为自己获取一个巨大的 android 存储库,或者也许是 Linux 内核,并在那里测试您的提示符。

  2. HEAD不是一个分支。它是指向签出状态的指针。当您签出一个分支时,它是对该分支的符号引用。当您处于“分离头”状态时,HEAD指针指向提交。您可以HEAD使用方法 (1) 获得返回值,因为rev-parse它只是回显错误中传递的 refspec 值。尝试使用blah; 你会看到同样的事情。

  3. 我实际上还没有对解决方案进行基准测试,但您可以尝试一些方法(两者都在我的 zsh 提示符中使用,这不是我编写的,并且两者都表现得很好):

    git rev-parse --is-inside-work-tree ;# avoids your 'test -d .git' call
    ref=$(git symbolic-ref HEAD 2> /dev/null) ;# grab the full refspec
    branch=$(echo ${ref#refs/heads/}) ;# extract the branch name
    
    Run Code Online (Sandbox Code Playgroud)