如何在我的 PowerShell 提示符中显示我当前的 git 分支名称?

Posted

技术标签:

【中文标题】如何在我的 PowerShell 提示符中显示我当前的 git 分支名称?【英文标题】:How can I display my current git branch name in my PowerShell prompt? 【发布时间】:2010-11-20 05:42:50 【问题描述】:

基本上我在使用this,但使用的是 PowerShell 而不是 bash。

我通过 PowerShell 在 Windows 上使用 git。如果可能的话,我希望我当前的分支名称显示为命令提示符的一部分。

【问题讨论】:

使用 Git 2.22(2019 年第二季度),不要忘记git branch --current 【参考方案1】:

更简单的方法是安装 Powershell 模块 posh-git。它开箱即用,带有所需的提示:

提示

PowerShell 通过执行提示函数(如果存在)来生成提示。 posh-git 在 profile.example.ps1 中定义了这样一个函数,它输出当前工作目录,后跟一个缩写的 git status:

C:\Users\Keith [master]>

默认情况下,状态摘要的格式如下:

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

(对于安装 posh-git,我建议使用 psget)

如果您没有 psget,请使用以下命令:

(new-object Net.WebClient).DownloadString("https://raw.githubusercontent.com/psget/psget/master/GetPsGet.ps1") | iex

要安装 posh-git,请使用以下命令: Install-Module posh-git

要确保为每个 shell 加载 posh-git,请使用 Add-PoshGitToProfile command。

【讨论】:

如何在启动时启用该模块?每次我打开一个新实例时,powershell 似乎都会忘记这个模块。 @Mihir 你必须创建一个配置文件,看看答案***.com/questions/24914589/… @NicolaPeluchetti 谢谢!我关注了howtogeek.com/50236/customizing-your-powershell-profile,并在我的powershell 配置文件中添加了Import-Module posh-git。像魅力一样工作! 如果您使用 Chocolatey,您可以在提升的命令提示符下使用 choco install poshgit 简单地安装 posh-git。 GetPsGet.ps1 现在位于“raw.githubusercontent.com/psget/psget/master/GetPsGet.ps1”。 “psget.net/GetPsGet.ps1”网址似乎不再存在。【参考方案2】:

这是我的看法。我对颜色进行了一些编辑,使其更具可读性。

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

示例 1:

示例 2:

【讨论】:

整洁!刚刚更改了我的背景颜色。你的背景颜色是什么? @YogeeshSeralathan 我正在为 ConEmu 使用 Monokai 主题。背景颜色为#272822 这很好用!如果它还可以显示一些迹象表明存在一些未提交的更改,那就太酷了。 Test-Path 不是递归的,只有当我们位于 git 项目的根目录时才会返回 true - 并非总是如此。 开箱即用。谢谢!【参考方案3】:

@保罗-

我的 Git PowerShell 配置文件基于我在此处找到的脚本:

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

我对其进行了一些修改以显示目录路径和一些格式。自从我使用 PortableGit 以来,它还设置了我的 Git bin 位置的路径。

# 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 " "
 

到目前为止,这非常有效。在 repo 中,提示很高兴地看起来像:

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

*注意:根据 Jakub Narębski 的建议进行了更新。

删除了 git 分支/git 状态调用。 解决了 'git config --global' 会失败的问题,因为没有设置 $HOME。 解决了浏览到没有 .git 目录的目录会导致格式恢复为 PS 提示符的问题。

【讨论】:

干杯大卫,我很容易修改它并使用链接博客文章中的说明来启动和运行适合我的东西。 不要抓取 git-branch 输出来获取当前分支的名称;它适用于最终用户(它是瓷器)。使用git symbolic-ref HEAD。不要使用 git-status;它适用于最终用户,可能会发生变化(它将在 1.7.0 中发生变化)。使用 git-diff-files、git-diff-tree、git-diff-index。 #Jakub Narębski - 根据您的建议更新了代码 - 非常感谢。由于它没有调用分支和状态,所以它也快了很多。【参考方案4】:

使用 Git 2.22(2019 年第二季度),任何脚本(无论是否使用 Powershell)都可以使用 the new --show-current option。

$branch = git branch --show-current

如果为空,则表示“分离的 HEAD”。

【讨论】:

@KarenGoh 它应该,除非您处于分离的 HEAD 模式。你用的是什么版本的 Git?【参考方案5】:

我调整了提示代码(来自@david-longnecker 的回答),使其更加丰富多彩。

编辑: 2019 年 6 月 - 更新为显示未跟踪、隐藏、重命名。调整视觉以显示索引。

为什么使用这个(通过 posh-git 等):

学习:在我调整时了解有关 git/SCM 概念的内容 最终修复了 posh-git 解决的问题,但我通过这个了解了更多 跨平台:在 POSIX shell 中具有相同的提示,代码几乎相同。 灵活:我已调整提示以显示未跟踪/隐藏/索引/重命名。 轻巧便携:无需获取外部模块(这是一个小好处,但很好)

powershell 代码:

注意: 使用的一些命令是瓷器(不推荐用于脚本/解析,例如git status)。最终将迁移到 plumbing 命令,但目前可行。

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

  #Do git fetch if no changes in last 10 minutes
  # Last Reflog: Last time upstream was updated
  # Last Fetch: Last time fetch/pull was ATTEMPTED
  # Between the two can identify when last updated or attempted a fetch.
  $MaxFetchSeconds = 600
  $upstream = $(git rev-parse --abbrev-ref "@upstream")
  $lastreflog = $(git reflog show --date=iso $upstream -n1)
  if ($lastreflog -eq $NULL) 
    $lastreflog = (Get-Date).AddSeconds(-$MaxFetchSeconds)
  
  else 
    $lastreflog = [datetime]$($lastreflog | % [Regex]::Matches($_, "(.*)") ).groups[1].Value
  
  $gitdir = $(git rev-parse --git-dir)
  $TimeSinceReflog = (New-TimeSpan -Start $lastreflog).TotalSeconds
  if (Test-Path $gitdir/FETCH_HEAD) 
    $lastfetch =  (Get-Item $gitdir/FETCH_HEAD).LastWriteTime
    $TimeSinceFetch = (New-TimeSpan -Start $lastfetch).TotalSeconds
   else 
    $TimeSinceFetch = $MaxFetchSeconds + 1
  
  #Write-Host "Time since last reflog: $TimeSinceReflog"
  #Write-Host "Time since last fetch: $TimeSinceFetch"
  if (($TimeSinceReflog -gt $MaxFetchSeconds) -AND ($TimeSinceFetch -gt $MaxFetchSeconds)) 
    git fetch --all | Out-Null
  

  #Identify stashes
  $stashes = $(git stash list 2>$NULL)
  if ($stashes -ne $NULL) 
    $git_stashes_count=($stashes | Measure-Object -Line).Lines
  
  else $git_stashes_count=0

  #Identify how many commits ahead and behind we are
  #by reading first two lines of `git status`
  #Identify how many untracked files (matching `?? `)
  $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]
      
      #Identify Added/UnTracked files
      elseIf ($_ -match '^A\s\s') 
        $git_index_added_count++
      
      elseIf ($_ -match '^\?\?\ ') 
        $git_untracked_count++
      

      #Identify Modified files
      elseIf ($_ -match '^MM\s') 
        $git_index_modified_count++
        $git_modified_count++
      
      elseIf ($_ -match '^M\s\s') 
        $git_index_modified_count++
      
      elseIf ($_ -match '^\sM\s') 
        $git_modified_count++
      

      #Identify Renamed files
      elseIf ($_ -match '^R\s\s') 
        $git_index_renamed_count++
      

      #Identify Deleted files
      elseIf ($_ -match '^D\s\s') 
        $git_index_deleted_count++
      
      elseIf ($_ -match '^\sD\s') 
        $git_deleted_count++
      

  
  $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 staged changes count, if any, in pretty colors
  If ($git_index_added_count -gt 0) 
    Write-Host (" Ai:") -nonewline -foregroundcolor White
    Write-Host ($git_index_added_count) -nonewline -foregroundcolor Green
  

  If ($git_index_renamed_count -gt 0) 
    Write-Host (" Ri:") -nonewline -foregroundcolor White
    Write-Host ($git_index_renamed_count) -nonewline -foregroundcolor DarkGreen
  

  If ($git_index_modified_count -gt 0) 
    Write-Host (" Mi:") -nonewline -foregroundcolor White
    Write-Host ($git_index_modified_count) -nonewline -foregroundcolor Yellow
  

  If ($git_index_deleted_count -gt 0) 
    Write-Host (" Di:") -nonewline -foregroundcolor White
    Write-Host ($git_index_deleted_count) -nonewline -foregroundcolor Red
  

  #Output unstaged changes count, if any, in pretty colors
  If (($git_index_added_count) -OR ($git_index_modified_count) -OR ($git_index_deleted_count)) 
    If (($git_modified_count -gt 0) -OR ($git_deleted_count -gt 0))  
      Write-Host (" |") -nonewline -foregroundcolor White
    
  

  If ($git_modified_count -gt 0) 
    Write-Host (" M:") -nonewline -foregroundcolor White
    Write-Host ($git_modified_count) -nonewline -foregroundcolor Yellow
  

  If ($git_deleted_count -gt 0) 
    Write-Host (" D:") -nonewline -foregroundcolor White
    Write-Host ($git_deleted_count) -nonewline -foregroundcolor Red
  

  If (($git_untracked_count -gt 0) -OR ($git_stashes_count -gt 0))  
    Write-Host (" |") -nonewline -foregroundcolor White
  

  If ($git_untracked_count -gt 0)  
    Write-Host (" untracked:") -nonewline -foregroundcolor White
    Write-Host ($git_untracked_count) -nonewline -foregroundcolor Red
  

  If ($git_stashes_count -gt 0)  
    Write-Host (" stashes:") -nonewline -foregroundcolor White
    Write-Host ($git_stashes_count) -nonewline -foregroundcolor Yellow
  

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



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



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

结果(VSCode,使用 Powershell 终端):

以下是来自结果的命令,用于查看结果:

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"
"test" >> ".test"
mv .gitignore1 .gitignore3
git add -A
git stash
git checkout "master"
cd c:\git\test #Just a sample repo had that was ahead 1 commit
#Remove-Item "c:\git\newrepo" -Recurse -Force #Cleanup

【讨论】:

绝对看起来不错....我在质疑每次在新提示出现之前按回车键时我是否可以忍受超过一秒的延迟...。 @xyious 根据 repo 大小,各种 git 命令可能需要一段时间来处理。有趣的是,这对我来说“很快”——进入我的一个 git 存储库可能只有几分之一秒的延迟。 有更好的方法(维护功能集)吗? 我在 dotfiles 存储库中维护它,并在基于 POSIX 的 shell 上提供匹配提示 - 它有助于一致性,更重要的是学习,并且易于阅读并理解(和调整)。最后,这个提示包括检查上游更改的非传统但很好的功能 - 如果它让我知道状态,我会稍微延迟一下。【参考方案6】:

posh-git 很慢,https://ohmyposh.dev/ 有更好的方法。

    从 powershell 运行此命令以安装 ohmyposh 模块:
Install-Module oh-my-posh -Scope CurrentUser -AllowPrerelease

    从https://www.nerdfonts.com/ 安装支持字形(图标)的字体。 我喜欢Meslo LGM NF。

    在 powershell 默认设置中设置该字体:

    C:\Program Files\PowerShell\7 打开/创建文件Microsoft.PowerShell_profile.ps1 并在下面写以设置主题(与截图相同):
Set-PoshPrompt -Theme aliens

您也可以选择其他主题。运行Get-PoshThemes查看预览

现在在包含 git repo 的位置打开 powershell,您将看到状态。

【讨论】:

【参考方案7】:

从@tamj0rd2 的回答中,我们可以将分支名称转换为这样的字符串变量。

$branch = git rev-parse --abbrev-ref HEAD
echo $branch

【讨论】:

【参考方案8】:

我喜欢接受的答案,因此我将详细说明设置它的步骤。 您可以使用 Chocolatey 或使用可用于新 Core PowerShell 的 PowerShellGet 命令安装 PoshGit。

对于 Chocolatey,您需要先安装它,然后再继续。 在管理员/提升的 shell 中执行命令:

choco install poshgit

对于 Core PowerShell,还需要安装。要安装 Core PowerShell,请执行以下命令:

dotnet tool install --global PowerShell

注意:您需要安装 .NET Core SDK(最好是最新版本)

安装Core PowerShell后,执行以下命令安装PoshGit:

PowerShellGet\Install-Module posh-git -Scope CurrentUser -AllowPrerelease -Force

使用 PoshGit 需要您使用命令 Import-Module posh-git 将其导入当前运行的 shell 环境。这意味着每次打开新 shell 时都必须运行此命令。

如果您希望 PoshGit 始终可用,则应改为执行以下命令:

Add-PoshGitToProfile

请注意,PowerShell 和 Core PowerShell 是不同的,因此它们在不同的配置文件上运行。这意味着,如果您希望 PoshGit 为任一 shell 工作,您需要在它们各自的 shell 环境中执行这些命令。

【讨论】:

【参考方案9】:

这是我对 PowerShell Core 的配置。只需复制下面的函数并将其放入您的$PROFILE

function prompt 
  try 
    $GitBranch = git rev-parse --abbrev-ref HEAD
    # we're probably in detached HEAD state, so print the SHA
    if ($GitBranch -eq "HEAD")  $GitBranch = git rev-parse --short HEAD 
   catch 

  if ($GitBranch)  $GitBranch = " `e[33;93m[`e[33;96m$GitBranch`e[33;93m]`e[0m" 

  "PS $pwd$GitBranch> "

【讨论】:

以上是关于如何在我的 PowerShell 提示符中显示我当前的 git 分支名称?的主要内容,如果未能解决你的问题,请参考以下文章

仅在 ISE 中运行的 Powershell 脚本

powershell自动提示、快速跳转、代理设置

从苏宁电器到卡巴斯基(第二部)第29篇:我当高校教师的这几年 V

从苏宁电器到卡巴斯基(第二部)第29篇:我当高校教师的这几年 V

powershell PowerShell的自定义提示,在切片栏中显示您当前的Az订阅

将 PowerShell 用于 Visual Studio 命令提示符