Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

While trying to set up my new fish shell prompt, I ended up testing ways to get the branch name and also testing if I was on a git repository. I have found (1) git rev-parse --abbrev-ref HEAD, (2) git symbolic-ref HEAD | sed 's/refs\/heads\///' and (3) git describe --contains --all HEAD do the trick just fine.

I’m curious because I love the simplicity of (1), but on a new and untouched (just git inited) repository, it gives me a “fatal:” error, while (2) works as intended, that is, giving me a default master as output. The thing is, even with a “fatal:” error, the return code is 0. Is that the intended behavior?

To test if I was in a git repository, I ended up simply testing if the current directory had a “.git” folder: test -d ".git". Rudimentary solution, but it works, and it seems to be faster that using any git command.

So, my questions are:

  1. Shouldn’t that “fatal:” with (1) return an exit code different from 0? If indeed it is a bug, since I don’t know how git people standardised their return codes, where should I report it?
  2. I know if I redirect (1) with ^ /dev/null (for those who don’t know, ^ is the same as 2>), I won’t get the error, but it will say HEAD instead of master, but if I cat .git/HEAD, I get: ref: refs/heads/master. What should it really say? With master am I just being ignorant and picky, because it should instead say HEAD? I mean in the case of a just git inited repository.
  3. Have you actually benchmarked any possible solutions during your quest to get a nice prompt?

This is the code I use to benchmark (for fish):

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

Thanks in advance!

PS: The tools are the latest GNU versions, I mean, sed, date and expr. I’m sorry if there is too much information or if something doesn’t make any sense. Bear with me. Thanks!

EDIT: As someone correctly guessed in an answer, the whole error is:

fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
share|improve this question
    
Please post the fatal: error. Tough to know how it should be treated without being able to read it. :-) –  Christopher Sep 12 '12 at 12:56
    
I just did it. :) –  Andrés Botero Sep 12 '12 at 19:46

1 Answer 1

up vote 2 down vote accepted

Doesn't fully answer your questions but probably a bit more than just a comment:

  1. Based on other comments in your answer, I think the error you saw is fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. That occurs because you're conducting these tests on a brand new git repository, one that has no committed work. Not only is this not really a fair test (your performance will by definition be worse on a larger repository), it is in nearly every way an edge case. For example, .git/HEAD shows ref: refs/heads/master by convention. The error is thrown because HEAD is ambiguous. You have no history, thus any value passed to rev-parse would be treated the same. Additionally, this doesn't exit 0 for me:

    $ git init /tmp/test && cd /tmp/test
    $ git rev-parse --abbrev-ref HEAD
    $ echo $?
    128
    

    In sum, don't sweat this error. Grab yourself one of the huge android repos, or perhaps the linux kernel, and test your prompt there.

  2. HEAD is not a branch. It's a pointer to the checked-out state. When you've got a branch checked out, it's a symbolic reference to that branch. When you're in 'detached HEAD' state, the HEAD pointer is pointing at a commit. You get HEAD as the return using method (1) because rev-parse is just echoing the passed refspec value in the error. Try it with blah; you'll see the same thing.

  3. I haven't actually benchmarked solutions, but a few things you might try (both are used in my zsh prompt, which I didn't write, and both have performed quite well):

    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
    
share|improve this answer
    
I’m not at home right now, but I’m going to try in my Android ROM source when I get back. Indeed what best place to try it out... Thanks! –  Andrés Botero Sep 12 '12 at 19:47
    
--is-inside-work-tree is a much better option (but not as fast, though) than testing .git directory, since .git is only in the root. For the branch, “git help symbolic-ref” gave me the answer: git symbolic-ref --short HEAD 2>/dev/null. Much cooler, a single command, perfect. No idea how I didn’t see it before. Thanks! –  Andrés Botero Sep 24 '12 at 6:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.