How can I display my current git branch name in my PowerShell prompt?

Basically I'm after this but for PowerShell instead of bash.

I use git on windows through PowerShell. If possible, I'd like my current branch name to displayed as part of the command prompt.

Answers


An easier way would be just installing the Powershell module posh-git. It comes out of the box with the desired prompt:

The Prompt

PowerShell generates its prompt by executing a prompt function, if one exists. posh-git defines such a function in profile.example.ps1 that outputs the current working directory followed by an abbreviated git status:

C:\Users\Keith [master]>

By default, the status summary has the following format:

[{HEAD-name} +A ~B -C !D | +E ~F -G !H]

(For installing posh-git I suggest using psget)

If you don't have psget use the following command:

(new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex

To install posh-git use the command: Install-Module posh-git

To ensure posh-git loads for every shell, use the Add-PoshGitToPrompt command.


@Paul-

My PowerShell profile for Git is based off of a script I found here:

http://techblogging.wordpress.com/2008/10/12/displaying-git-branch-on-your-powershell-prompt/

I've modified it a bit to display the directory path and a bit of formatting. It also sets the path to my Git bin location since I use PortableGit.

# General variables
$pathToPortableGit = "D:\shared_tools\tools\PortableGit"
$scripts = "D:\shared_tools\scripts"

# Add Git executables to the mix.
[System.Environment]::SetEnvironmentVariable("PATH", $Env:Path + ";" + (Join-Path $pathToPortableGit "\bin") + ";" + $scripts, "Process")

# Setup Home so that Git doesn't freak out.
[System.Environment]::SetEnvironmentVariable("HOME", (Join-Path $Env:HomeDrive $Env:HomePath), "Process")

$Global:CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$UserType = "User"
$CurrentUser.Groups | foreach { 
    if ($_.value -eq "S-1-5-32-544") {
        $UserType = "Admin" } 
    }

function prompt {
     # Fun stuff if using the standard PowerShell prompt; not useful for Console2.
     # This, and the variables above, could be commented out.
     if($UserType -eq "Admin") {
       $host.UI.RawUI.WindowTitle = "" + $(get-location) + " : Admin"
       $host.UI.RawUI.ForegroundColor = "white"
      }
     else {
       $host.ui.rawui.WindowTitle = $(get-location)
     }

    Write-Host("")
    $status_string = ""
    $symbolicref = git symbolic-ref HEAD
    if($symbolicref -ne $NULL) {
        $status_string += "GIT [" + $symbolicref.substring($symbolicref.LastIndexOf("/") +1) + "] "

        $differences = (git diff-index --name-status HEAD)
        $git_update_count = [regex]::matches($differences, "M`t").count
        $git_create_count = [regex]::matches($differences, "A`t").count
        $git_delete_count = [regex]::matches($differences, "D`t").count

        $status_string += "c:" + $git_create_count + " u:" + $git_update_count + " d:" + $git_delete_count + " | "
    }
    else {
        $status_string = "PS "
    }

    if ($status_string.StartsWith("GIT")) {
        Write-Host ($status_string + $(get-location) + ">") -nonewline -foregroundcolor yellow
    }
    else {
        Write-Host ($status_string + $(get-location) + ">") -nonewline -foregroundcolor green
    }
    return " "
 }

So far, this has worked really well. While in a repo, the prompt happily looks like:

GIT [master] c:0 u:1 d:0 | J:\Projects\forks\fluent-nhibernate>

*NOTE: Updated with suggestions from Jakub Narębski.

  • Removed git branch/git status calls.
  • Addressed an issue where 'git config --global' would - fail because $HOME was not set.
  • Addressed an issue where browsing to a directory that didn't have the .git directory would cause the formatting to revert to the PS prompt.

Here's my take on it. I've edited the colours a bit to make it more readable.

Microsoft.PowerShell_profile.ps1

function Write-BranchName () {
    try {
        $branch = git rev-parse --abbrev-ref HEAD

        if ($branch -eq "HEAD") {
            # we're probably in detached HEAD state, so print the SHA
            $branch = git rev-parse --short HEAD
            Write-Host " ($branch)" -ForegroundColor "red"
        }
        else {
            # we're on an actual branch, so print it
            Write-Host " ($branch)" -ForegroundColor "blue"
        }
    } catch {
        # we'll end up here if we're in a newly initiated git repo
        Write-Host " (no branches yet)" -ForegroundColor "yellow"
    }
}

function prompt {
    $base = "PS "
    $path = "$($executionContext.SessionState.Path.CurrentLocation)"
    $userPrompt = "$('>' * ($nestedPromptLevel + 1)) "

    Write-Host "`n$base" -NoNewline

    if (Test-Path .git) {
        Write-Host $path -NoNewline -ForegroundColor "green"
        Write-BranchName
    }
    else {
        # we're not in a repo so don't bother displaying branch name/sha
        Write-Host $path -ForegroundColor "green"
    }

    return $userPrompt
}

Example 1:

Example 2:


I tweaked the prompt code (from @david-longnecker answer) to be a bit more colorful.

Edit: Oct 2018 - Reworked with additional comments, some cleanup, a less noisy output than before.

The powershell code:

Function Prompt {

$SYMBOL_GIT_BRANCH='⑂'
$SYMBOL_GIT_MODIFIED='*'
$SYMBOL_GIT_PUSH='↑'
$SYMBOL_GIT_PULL='↓'

if (git rev-parse --git-dir 2> $null) {

  $symbolicref = $(git symbolic-ref --short HEAD 2>$NULL)

  if ($symbolicref) {#For branches append symbol
    $branch = $symbolicref.substring($symbolicref.LastIndexOf("/") +1)
    $branchText=$SYMBOL_GIT_BRANCH + ' ' + $branch
  } else {#otherwise use tag/SHA
      $symbolicref=$(git describe --tags --always 2>$NULL)
      $branch=$symbolicref
      $branchText=$symbolicref
  }

} else {$symbolicref = $NULL}


if ($symbolicref -ne $NULL) {
  # Tweak: 
  # When WSL and Powershell terminals concurrently viewing same repo
  # Stops from showing CRLF/LF differences as updates
  git status > $NULL

  $differences = $(git diff-index --name-status HEAD)

  If ($differences -ne $NULL) {
    $git_create_count = [regex]::matches($differences, "A`t").count
    $git_update_count = [regex]::matches($differences, "M`t").count
    $git_delete_count = [regex]::matches($differences, "D`t").count
  }
  else {
    $git_create_count = 0
    $git_update_count = 0
    $git_delete_count = 0
  }

  #Identify how many commits ahead and behind we are
  #by reading first two lines of `git status`
  $marks=$NULL
  (git status --porcelain --branch 2>$NULL) | ForEach-Object { 

      If ($_ -match '^##') {
        If ($_ -match 'ahead\ ([0-9]+)') {$git_ahead_count=[int]$Matches[1]}
        If ($_ -match 'behind\ ([0-9]+)') {$git_behind_count=[int]$Matches[1]}
      }
  }
  $branchText+="$marks"


}

if (test-path variable:/PSDebugContext) { 
  Write-Host '[DBG]: ' -nonewline -foregroundcolor Yellow
}

Write-Host "PS " -nonewline -foregroundcolor White
Write-Host $($executionContext.SessionState.Path.CurrentLocation) -nonewline -foregroundcolor White

if ($symbolicref -ne $NULL) {
  Write-Host (" [ ") -nonewline -foregroundcolor Magenta

  #Output the branch in prettier colors
  If ($branch -eq "master") {
    Write-Host ($branchText) -nonewline -foregroundcolor White
  }
  else {Write-Host $branchText -nonewline -foregroundcolor Red}

  #Output commits ahead/behind, in pretty colors
  If ($git_ahead_count -gt 0) {
      Write-Host (" $SYMBOL_GIT_PUSH") -nonewline -foregroundcolor White
      Write-Host ($git_ahead_count) -nonewline -foregroundcolor Green
  }
  If ($git_behind_count -gt 0) {
      Write-Host (" $SYMBOL_GIT_PULL") -nonewline -foregroundcolor White
      Write-Host ($git_behind_count) -nonewline -foregroundcolor Yellow
  }

  #Output unstaged changes count, if any, in pretty colors   
  If ($git_create_count -gt 0) {
      Write-Host (" c:") -nonewline -foregroundcolor White
      Write-Host ($git_create_count) -nonewline -foregroundcolor Green
  }

  If ($git_update_count -gt 0) {
    Write-Host (" u:") -nonewline -foregroundcolor White
    Write-Host ($git_update_count) -nonewline -foregroundcolor Yellow
  }

  If ($git_delete_count -gt 0) {
    Write-Host (" d:") -nonewline -foregroundcolor White
    Write-Host ($git_delete_count) -nonewline -foregroundcolor Red
  }

  Write-Host (" ]") -nonewline -foregroundcolor Magenta

}

$(Write-Host $('>' * ($nestedPromptLevel + 1)) -nonewline -foregroundcolor White)



return " "}#Powershell requires a return, otherwise defaults to factory prompt

The result (VSCode, Using Powershell terminal):

Here are commands from result to view what it would look like:

mkdir c:\git\newrepo | Out-Null
cd c:\git\newrepo
git init
"test" >> ".gitignore"
"test" >> ".gitignore2"
git add -A
git commit -m "test commit" | Out-Null
"test" >> ".gitignore1"
git add -A
"test1" >> ".gitignore2"
git rm .gitignore
git add -A
git commit -m "test commit2" | Out-Null
git checkout -b "newfeature1"
git checkout "master"
cd c:\git\test #Just a sample repo had that was ahead 1 commit

Need Your Help

Identify via Youtube data API whether advertisements can be displayed on/before/next to a specific video

video youtube youtube-api advertising youtube-data-api

Is there a possibility to check via the Youtube data API whether advertisements can be displayed with a specific video?

Getting the Raspberry Pi compatible with the IFTTT Maker channel

webserver raspberry-pi iot webiopi

I'm really wondering what would be an efficient way to control your gpios or run scripts with the new ifttt.com/maker channel. It's really easy to trigger something from the raspberry pi, you just ...