如何在我的 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
How can I display my current git branch name in my PowerShell prompt?
提问by Paul Batum
采纳答案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-PoshGitToProfile
command.
要确保为每个 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:
Example 2:
示例 2:
回答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):
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-current
option.
使用 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 PowerShellGet
command 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 环境中执行这些命令。