86

基本上我在之后,但对于 PowerShell 而不是 bash。

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

4

9 回答 9

67

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

提示

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

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命令.

于 2012-04-11T13:28:45.743 回答
39

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

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:

在此处输入图像描述

于 2017-06-07T11:18:57.317 回答
24

@保罗-

我的 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 [主] c:0 u:1 d:0 | J:\Projects\forks\fluent-nhibernate>

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

  • 删除了 git branch/git status 调用。
  • 解决了 'git config --global' 会失败的问题,因为 $HOME 未设置。
  • 解决了浏览到没有 .git 目录的目录会导致格式恢复为 PS 提示的问题。
于 2009-08-17T13:15:49.290 回答
5

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

$branch = git branch --show-current

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

于 2019-09-27T16:03:17.173 回答
5

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

在此处输入图像描述

  1. 从 powershell 运行此命令以安装ohmyposh模块:
Install-Module oh-my-posh -Scope CurrentUser -AllowPrerelease
  1. 从https://www.nerdfonts.com/安装支持字形(图标)的字体。
    我喜欢Meslo LGM NF

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

在此处输入图像描述

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

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

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


查看更多:启动您的 PowerShell

于 2021-01-08T15:56:47.287 回答
3

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

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

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

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

电源外壳代码:

注意:使用的一些命令是瓷器(不推荐用于脚本/解析,例如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

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

以下是来自 result 的命令,用于查看它的外观:

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
于 2017-03-08T21:15:03.550 回答
1

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

$branch = git rev-parse --abbrev-ref HEAD
echo $branch
于 2019-09-27T11:11:29.283 回答
1

我喜欢接受的答案,所以我将详细说明设置它的步骤。PowerShellGet您可以使用 Chocolatey 或使用可用于新 Core PowerShell的命令安装 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 环境中执行这些命令。

于 2020-02-21T04:04:54.013 回答
0

这是我对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> "
}
于 2021-04-08T23:03:19.927 回答