Skip to content

Instantly share code, notes, and snippets.

@bingzhangdai
Last active May 23, 2025 03:42
Show Gist options
  • Save bingzhangdai/dd4e283a14290c079a76c4ba17f19d69 to your computer and use it in GitHub Desktop.
Save bingzhangdai/dd4e283a14290c079a76c4ba17f19d69 to your computer and use it in GitHub Desktop.
Fastest way to get git branch

Sometimes, we want to show current git branch in Bash prompt. git symbolic-ref --short -q HEAD is too slow, especially in WSL. Here is a pure Bash version to print git branch.

function _get_git_branch() {
    local _head_file _head
    local _dir="$PWD"

    while [[ -n "$_dir" ]]; do
        _head_file="$_dir/.git/HEAD"
        if [[ -f "$_dir/.git" ]]; then
            read -r _head_file < "$_dir/.git" && _head_file="$_dir/${_head_file#gitdir: }/HEAD"
        fi
        [[ -e "$_head_file" ]] && break
        _dir="${_dir%/*}"
    done

    if [[ -e "$_head_file" ]]; then
        read -r _head < "$_head_file" || return
        case "$_head" in
            ref:*) printf "${_head#ref: refs/heads/}" ;;
            "") ;;
            # HEAD detached
            *) printf "${_head:0:9}" ;;
        esac
        return 0
    fi

    return 1
}

It is tremendously faster than git command (1ms vs 74ms). Tested on Ubuntu 20.04 (WSL1),

david@Ubuntu:/m/c/U/b/R/T/E/M/T/teeProxyConsole[develop]$ time git symbolic-ref --short -q HEAD
develop

real    0m0.074s
user    0m0.000s
sys     0m0.016s
david@Ubuntu:/m/c/U/b/R/T/E/M/T/teeProxyConsole[develop]$ time _get_git_branch
develop
real    0m0.001s
user    0m0.000s
sys     0m0.016s
@dtucny
Copy link

dtucny commented May 23, 2025

I'm not sure what triggered it exactly, but, experienced a significant slowdown on the prompt display in git-bash on Windows.

Placing the following in ~/.config/git/git-prompt.sh works like a charm (modified the original slightly to provide equivalent output to __git_ps1).

#!/usr/bin/bash

function _get_git_branch() {
    local _head_file _head
    local _dir="$PWD"

    while [[ -n "$_dir" ]]; do
        _head_file="$_dir/.git/HEAD"
        if [[ -f "$_dir/.git" ]]; then
            read -r _head_file < "$_dir/.git" && _head_file="$_dir/${_head_file#gitdir: }/HEAD"
        fi
        [[ -e "$_head_file" ]] && break
        _dir="${_dir%/*}"
    done

    if [[ -e "$_head_file" ]]; then
        read -r _head < "$_head_file" || return
        case "$_head" in
                ref:*) printf " (${_head#ref: refs/heads/})" ;;
            "") ;;
            # HEAD detached
            *) printf " (${_head:0:9})" ;;
        esac
        return 0
    fi

    return 1
}

PS1='\[\033]0;$TITLEPREFIX:$PWD\007\]' # set window title
PS1="$PS1"'\n'                 # new line
PS1="$PS1"'\[\033[32m\]'       # change to green
PS1="$PS1"'\u@\h '             # user@host<space>
PS1="$PS1"'\[\033[35m\]'       # change to purple
PS1="$PS1"'$MSYSTEM '          # show MSYSTEM
PS1="$PS1"'\[\033[33m\]'       # change to brownish yellow
PS1="$PS1"'\w'                 # current working directory
if test -z "$WINELOADERNOEXEC"
then
        GIT_EXEC_PATH="$(git --exec-path 2>/dev/null)"
        COMPLETION_PATH="${GIT_EXEC_PATH%/libexec/git-core}"
        COMPLETION_PATH="${COMPLETION_PATH%/lib/git-core}"
        COMPLETION_PATH="$COMPLETION_PATH/share/git/completion"
        if test -f "$COMPLETION_PATH/git-prompt.sh"
        then
                . "$COMPLETION_PATH/git-completion.bash"
                . "$COMPLETION_PATH/git-prompt.sh"
                PS1="$PS1"'\[\033[36m\]'  # change color to cyan
                PS1="$PS1"'`_get_git_branch`'   # bash function
        fi
fi
PS1="$PS1"'\[\033[0m\]'        # change color
PS1="$PS1"'\n'                 # new line
PS1="$PS1"'$ '                 # prompt: always $

$ time __git_ps1
(main)
real 0m0.770s
user 0m0.030s
sys 0m0.046s

$ time _get_git_branch
(main)
real 0m0.001s
user 0m0.000s
sys 0m0.000s

@bingzhangdai
Copy link
Author

@dtucny because git command works poorly on Windows with lots of small files (you can try git status). This is also my pain point on Win. My version is just to read the HEAD file and get the branch name from file.
Glad to hear it helps :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment