Repository: xonsh/xonsh

Issue:
`curr_branch` gets nothing on xonsh
<!--- Provide a general summary of the issue in the Title above -->
<!--- If you have a question along the lines of "How do I do this Bash command in xonsh"
please first look over the Bash to Xonsh translation guide: https://xon.sh/bash_to_xsh.html
If you don't find an answer there, please do open an issue! -->

## xonfig

<details>

```
$ xonfig
+------------------+-----------------+
| xonsh            | 0.10.0          |
| Python           | 3.9.6           |
| PLY              | 3.11            |
| have readline    | True            |
| prompt toolkit   | 3.0.19          |
| shell type       | prompt_toolkit  |
| history backend  | json            |
| pygments         | 2.10.0          |
| on posix         | True            |
| on linux         | True            |
| distro           | arch            |
| on wsl           | False           |
| on darwin        | False           |
| on windows       | False           |
| on cygwin        | False           |
| on msys2         | False           |
| is superuser     | False           |
| default encoding | utf-8           |
| xonsh encoding   | utf-8           |
| encoding errors  | surrogateescape |
| on jupyter       | False           |
| jupyter kernel   | None            |
| xontrib 1        | coreutils       |
| xontrib 2        | onepath         |
| xontrib 3        | z               |
+------------------+-----------------+
```

</details>

## Expected Behavior
<!--- Tell us what should happen -->
The `curr_branch` shows branch in prompt

## Current Behavior
<!--- Tell us what happens instead of the expected behavior -->

Shows nothing. 

## Steps to Reproduce
<!--- Please try to write out a minimal reproducible snippet to trigger the bug, it will help us fix it! -->
Here's my xonshrc:

<details>

```python
from re import finditer
from os import getcwd, path, chdir
from xonsh.tools import EnvPath

xontrib load coreutils onepath z
$VI_MODE = True
$PROMPT = '{BLUE}{cwd} {curr_branch}\n{PURPLE}❯ '

$PATH += ['~/.local/bin',
          '~/.yarn/bin',
	  '~/usr/lib/jvm/default/bin']
$CLASSPATH = ['.', '/usr/bin/share/java/antlr-complete.jar']
$VISUAL = 'nvim'
$EDITOR = 'nvim'
$PAGER = 'page'

for m in finditer(r"export ([A-Z_]+)='([^']*)'", $(luarocks path)):
    env_var = m.group(1)
    if env_var == 'PATH':
        ${env_var} = EnvPath(m.group(2))
    else:
        ${env_var} = m.group(2)

def edit_neovim_config():
    wd = getcwd()
    chdir(path.expanduser('~/.config/nvim'))
    nvim init.lua
    chdir(wd)

aliases['e'] = 'nvim'
aliases['en'] = 'nvim -u NONE'
aliases['er'] = 'sudoedit'
aliases['ec'] = edit_neovim_config
aliases['g'] = 'git'
aliases['l'] = aliases['ls']
aliases['c'] = 'cd'
aliases['i'] = 'sudo light'
aliases['p'] = 'proxychains'
aliases['pg'] = 'proxychains git'
aliases['pa'] = 'proxychains paru'
aliases['a'] = 'paru'
aliases['h'] = 'chezmoi'
aliases['rm'] = 'rm -i'
aliases['tp'] = 'trash-put'
aliases['tl'] = 'trash-list'
aliases['te'] = 'trash-empty'
```

</details>

## For community
⬇️  **Please click the 👍 reaction instead of leaving a `+1` or 👍  comment**



Discussion:
OK, I have to add here that the branch appears sometimes, but when I'm in '/tmp' and init it as if it's a git repo, there's no branch tag occur. 
I can't reproduce this on Arch.

Offtopic:
> $PROMPT = '{BLUE}{cwd} {curr_branch}\n{PURPLE}❯ '

You can try [xontrib-prompt-bar](https://github.com/anki-code/xontrib-prompt-bar), [xontrib-prompt-starship](https://github.com/anki-code/xontrib-prompt-starship) or pure [Starship](https://github.com/starship/starship).
[![asciicast](https://asciinema.org/a/BbNF0CZl1r73zsfSzEnT4v98m.svg)](https://asciinema.org/a/BbNF0CZl1r73zsfSzEnT4v98m)
I can repeat this and it looks like the branch name will appear after the first commit:
```
/tmp 
❯ git init .

/tmp 
❯ touch 123

/tmp 
❯ git add 123

/tmp 
❯ git commit -m 'first'

/tmp master
❯ 
```
Yeah, it's the same on my machine. 
So we can check the code that returns git branch:

https://github.com/xonsh/xonsh/blob/948129b7a0cdb734ac0d025b4393c9924b0b0ca0/xonsh/prompt/vc.py#L32-L39

Try to repeat:

```bash
xonsh --no-rc
cd /tmp
rm -rf .git
git init .

@(["git", "rev-parse", "--abbrev-ref", "HEAD"])
# HEAD
# fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
# Use '--' to separate paths from revisions, like this:
# 'git <command> [<revision>...] -- [<file>...]'

# Let's check also:
git branch
# No result

touch 123
git add 123
git commit -m "first"
@(["git", "rev-parse", "--abbrev-ref", "HEAD"])
# master
git branch 
# * master
```

So what do you suggest to show in this case? PR is welcome!
Maybe use `git branch --show-current`, but this requires Git 2.22 and above.
> git branch --show-current

Yep, it's working. PR is welcome!

Resolving patch:
diff --git a/xonsh/prompt/vc.py b/xonsh/prompt/vc.py
--- a/xonsh/prompt/vc.py
+++ b/xonsh/prompt/vc.py
@@ -1,6 +1,6 @@
 """Prompt formatter for simple version control branches"""
 # pylint:disable=no-member, invalid-name
-
+import contextlib
 import os
 import pathlib
 import queue
@@ -29,13 +29,18 @@ def _run_git_cmd(cmd):
 
 
 def _get_git_branch(q):
-    try:
-        cmd = ["git", "rev-parse", "--abbrev-ref", "HEAD"]
-        branch = xt.decode_bytes(_run_git_cmd(cmd))
-    except (subprocess.CalledProcessError, OSError):
-        q.put(None)
-    else:
-        q.put(branch.splitlines()[0] if branch else None)
+    # from https://git-blame.blogspot.com/2013/06/checking-current-branch-programatically.html
+    for cmds in [
+        "git symbolic-ref --short HEAD",
+        "git show-ref --head -s --abbrev",  # in detached mode return sha1
+    ]:
+        with contextlib.suppress(subprocess.CalledProcessError, OSError):
+            branch = xt.decode_bytes(_run_git_cmd(cmds.split()))
+            if branch:
+                q.put(os.path.basename(branch.splitlines()[0]))
+                return
+    # all failed
+    q.put(None)
 
 
 def get_git_branch():


Test patch: