Hmm… I want to show the current branch and status of my Git repository on my Windows PowerShell prompt. I found a post on Stack Overflow that gives a good example of showing Git repo status on a PowerShell prompt, but I customized it a bit to show data I want to see.

Git status on my PowerShell prompt when the index and working directory are clean:

Git PowerShell Prompt Nothing To Commit Working Directory Clean

When there are differences in the Git index or in the working folder then the prompt will look like the following:

Git PowerShell Prompt With Index And Working Directory Changes

The meaning of the status is documented on the git-status man page for the --s, –short, or --porcelain argument. I’m using git status –porcelain, as it not supposed to change in the future. Please note that I replace the space in the status with a dash.

GitStatusKey

The script for the profile.ps1 file follows:

$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("")
   $statusString = ""
   $symbolicref = git symbolic-ref HEAD
   if($symbolicref -ne $NULL)
   {
      $statusString += "GIT [" + $symbolicref.substring($symbolicref.LastIndexOf("/") +1) + "] "

      $status = git status --porcelain #--untracked-files=all
   
      if ( $status )
      {
         $matches = [regex]::matches([system.string]::join("`n", $status), "(?m)^.{2}")
         
         $statusTotals =  # Create hash table
         
         foreach ( $match in $matches )
         {
            if ( ![string]::IsNullOrEmpty($match.Value) )
            {
               $matchValue = $match.Value.Replace(" ", "-")
               
               if ( !$statusTotals.ContainsKey($matchValue) )
               {
                  $statusTotals.Add($matchValue, 1)
               }
               else
               {
                  $statusTotals.Set_Item($matchValue, $statusTotals.Get_Item($matchValue) + 1)
               }
            }
         }
   
         foreach ( $dictEntry in $statusTotals.GetEnumerator() | Sort-Object Name)
         {
            $statusString += $outVal = [string]::format("{0}:{1} ", $dictEntry.Name, $dictEntry.Value)
         }
      }
      else
      {
         $statusString += "nothing to commit (working dir clean)"
      }
   }
   else
   {
      $statusString = "PS "
   }

   if ($statusString.StartsWith("GIT")) {
      Write-Host ($statusString + [System.Environment]::NewLine + $(get-location) + ">") -nonewline -foregroundcolor yellow
   }
   else {
      Write-Host ($statusString + $(get-location) + ">") -nonewline -foregroundcolor green
   }
   return " "
}

You can place your profile.ps1 file in your ~\Document\WindowsPowerShell folder.

I created a short screen cast to go over the Git PowerShell prompt as well:

Hope you like it :-) It has brought me much Git PowerShell happiness :-D

Technical PowerShell Git July 21, 2010