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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1287718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:54:12  来源:igfitidea点击:

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

gitpowershellcommand-prompt

提问by Paul Batum

Basically I'm after thisbut for PowerShell instead of bash.

基本上我在追求这个,但对于 PowerShell 而不是 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.

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

采纳答案by sevenforce

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

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

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]

提示

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

C:\Users\Keith [master]>

默认情况下,状态摘要具有以下格式:

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

(For installing posh-git I suggest using psget)

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

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

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

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

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

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

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

要确保为每个 shell 加载 posh-git,请使用Add-PoshGitToProfile命令.

回答by David R. Longnecker

@Paul-

@保罗-

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

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

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

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.

我对其进行了一些修改以显示目录路径和一些格式。由于我使用 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 " "
 }

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

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

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

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

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

*注意:根据 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.
  • 删除了 git branch/git status 调用。
  • 解决了“git config --global”会失败的问题,因为 $HOME 未设置。
  • 解决了浏览到没有 .git 目录的目录会导致格式恢复为 PS 提示的问题。

回答by tamj0rd2

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

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

Microsoft.PowerShell_profile.ps1

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:

示例 1:

enter image description here

在此处输入图片说明

Example 2:

示例 2:

enter image description here

在此处输入图片说明

回答by PotatoFarmer

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

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

Edit:June 2019 - Updated to show untracked, stashes, renames. Tweaked visual to show index.

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

Why Iuse this(over posh-git etc):

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

  • Learning: Learn stuff about git/SCM concepts when as I tweak
    • End up fixing problems solved by posh-git, but I learn more through this
  • Cross Platform: Have same prompt in POSIX shells, code is almost identical.
  • Flexible: I've tweaked my Prompt to show untracked/stashes/index/renames.
  • Lightweight & Portable: No fetching external modules (this is minor benefit, but nice)
  • 学习:在我调整时学习有关 git/SCM 概念的东西
    • 最终解决了由 posh-git 解决的问题,但我通过这个学到了更多
  • 跨平台:在 POSIX shell 中具有相同的提示,代码几乎相同。
  • 灵活:我调整了我的提示以显示未跟踪/隐藏/索引/重命名。
  • 轻巧便携:无需获取外部模块(这是次要的好处,但很好)

The powershell code:

电源外壳代码:

NOTE:Some commands used are porcelain (not recommended for scripting/parsing, e.g. git status). Will eventually migrate to plumbingcommands, but this works for now.

注意:一些使用的命令是瓷器(不推荐用于脚本/解析,例如git status)。最终将迁移到管道命令,但这暂时有效。

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

The result (VSCode, Using Powershell terminal): Powershell Git Prompt in action

结果(VSCode,使用 Powershell 终端): Powershell Git 提示在行动

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

回答by Caveman

From @tamj0rd2's answer we can get the branch name to a string variable like this.

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

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

回答by VonC

With Git 2.22 (Q2 2019), any script (Powershell or not) could use the new --show-currentoption.

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

$branch = git branch --show-current

If empty, it means "detached HEAD".

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

回答by codejockie

I like the accepted answer so I will elaborate on the steps to set it up. You can install PoshGit using Chocolatey or using the PowerShellGetcommand which is available for the new Core PowerShell.

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

For Chocolatey, you need to have it already installed before proceeding. In an administrator/elevated shell execute the command:

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

choco install poshgit

For Core PowerShell, installation is also required. To install Core PowerShell, execute the following command:

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

dotnet tool install --global PowerShell

NB: You need to have .NET Core SDK installed (latest version preferably)

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

After installing Core PowerShell, execute the command below to install PoshGit:

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

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

Using PoshGit requires you import it to the currently running shell environment using the command Import-Module posh-git. This means you have to run this command every time you open a new shell.

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

If you want PoshGit to be always available you should execute this command instead:

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

Add-PoshGitToProfile

Please note that PowerShell and Core PowerShell are different and as a result they run on different profiles. What this means is that if you want PoshGit to work for either of the shells you need to execute those commands in their respective shell environment.

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