从PowerShell脚本中提取时出错 [英] Error when pulling from PowerShell script
问题描述
我有一个简单的PowerShell脚本,可以使文件夹与其git存储库保持最新.
Param(
[Parameter(Mandatory = $true)][string]$branch,
[string]$location,
[int]$depth
)
Get-ChildItem -Recurse -Directory -Depth $depth -Filter _$branch -Name -Path $location |
ForEach-Object {
Write-Output "`n$("{0:MM/dd/yy} {0:HH:mm:ss}" -f (Get-Date)): Getting latest from $location$_"
git -C $location$_ pull
} *>> logs\$branch.log
当存储库是最新的时,它可以正常工作.但是,如果不是,则为输出:
07/29/19 14:47:27: Getting latest from somepath git : From https://gitlab.com/someplace At someplace\UpdateBranch.ps1:10 char:5 + git -C $location$_ pull + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (From https://gi...n/somerepo:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError b34e5d0..3ec9561 develop -> origin/develop b6d33b1..65fb520 feature/feature1 -> origin/feature/feature1 * [new branch] feature/feature2 -> origin/feature/feature2 c3fe1c9..9553b72 master -> origin/master Updating b34e5d0..3ec9561 Fast-forward stylesheet.scss | 4 ++-- ... 6 files changed, 11 insertions(+), 10 deletions(-)
似乎可以进行更新,但也会输出错误.
Git将更详细的数据写入Error流,以允许解析器解析最重要的位.然后,这些解析器可以忽略针对人类用户的更为冗长的输出.该数据通过stderr流发送. Powershell默认将stderr上的数据转换为错误记录,并抛出您看到的错误.
以下 github问题有很多可能的解决方案. /p>
似乎最简单的方法是添加--porcelain
或--quiet
,它们不会写将详细数据复制到stderr或完全没有数据.
git checkout branch --porcelain
git checkout branch --quiet
另一种选择是在整个环境中为git配置标准重定向模式,至少这样,您无需将重定向分散到整个代码中:
$env:GIT_REDIRECT_STDERR = '2>&1'
在中可以找到更多选项这个StackOverflow答案,将所有重定向的消息强制为其字符串表示形式也可以很好地工作:
git checkout branch 2>&1 | %{ "$_" }
另一种语法是:
"$(git checkout branch ? 2>&1 )"
另一种解决方法是通过cmd
调用git:
& cmd /c 'git checkout branch 2>&1'
在这个答案中您将找到一个包装函数,以一种干净的方式调用git .
function Invoke-Git {
<#
.Synopsis
Wrapper function that deals with Powershell's peculiar error output when Git uses the error stream.
.Example
Invoke-Git ThrowError
$LASTEXITCODE
#>
[CmdletBinding()]
param(
[parameter(ValueFromRemainingArguments=$true)]
[string[]]$Arguments
)
& {
[CmdletBinding()]
param(
[parameter(ValueFromRemainingArguments=$true)]
[string[]]$InnerArgs
)
C:\Full\Path\To\git.exe $InnerArgs
} -ErrorAction SilentlyContinue -ErrorVariable fail @Arguments
if ($fail) {
$fail.Exception
}
}
# Could shorten the function name. I instead alias it, for terseness.
Set-Alias -Name git -Value Invoke-Git
# Also alias the name with the extension, as it is called by some applications this way.
Set-Alias -Name git.exe -Value Invoke-Git
I have a simple PowerShell script to keep a folder up-to-date with its git repository.
Param(
[Parameter(Mandatory = $true)][string]$branch,
[string]$location,
[int]$depth
)
Get-ChildItem -Recurse -Directory -Depth $depth -Filter _$branch -Name -Path $location |
ForEach-Object {
Write-Output "`n$("{0:MM/dd/yy} {0:HH:mm:ss}" -f (Get-Date)): Getting latest from $location$_"
git -C $location$_ pull
} *>> logs\$branch.log
It works fine when the repository is already up-to-date. However, when it isn't, this is the output:
07/29/19 14:47:27: Getting latest from somepath git : From https://gitlab.com/someplace At someplace\UpdateBranch.ps1:10 char:5 + git -C $location$_ pull + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (From https://gi...n/somerepo:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError b34e5d0..3ec9561 develop -> origin/develop b6d33b1..65fb520 feature/feature1 -> origin/feature/feature1 * [new branch] feature/feature2 -> origin/feature/feature2 c3fe1c9..9553b72 master -> origin/master Updating b34e5d0..3ec9561 Fast-forward stylesheet.scss | 4 ++-- ... 6 files changed, 11 insertions(+), 10 deletions(-)
It seems to do the update but also outputs an error.
Git writes the more verbose data to the Error stream to allow parsers to parse the most important bits. These parsers can then ignore the more verbose output that's meant for the human user. That data is sent through the stderr stream. Powershell converts data on stderr to an error record by default, throwing the error you see.
The following github issue has a whole bunch of possible solutions.
The one that seems to be the simplest is to add --porcelain
or --quiet
, which will not write verbose data to stderr or no data at all.
git checkout branch --porcelain
git checkout branch --quiet
Another option is to configure the standard redirect mode for git through the environment, at least this way you don't need to scatter the redirect throughout the whole code:
$env:GIT_REDIRECT_STDERR = '2>&1'
More options are found in this StackOverflow answer, forcing all redirected messages to their string representation works nicely too:
git checkout branch 2>&1 | %{ "$_" }
An alternate syntax for that is:
"$(git checkout branch ? 2>&1 )"
Another workaround is to invoke git through cmd
:
& cmd /c 'git checkout branch 2>&1'
And in this answer you'll find a wrapper function to call git in a clean manner.
function Invoke-Git {
<#
.Synopsis
Wrapper function that deals with Powershell's peculiar error output when Git uses the error stream.
.Example
Invoke-Git ThrowError
$LASTEXITCODE
#>
[CmdletBinding()]
param(
[parameter(ValueFromRemainingArguments=$true)]
[string[]]$Arguments
)
& {
[CmdletBinding()]
param(
[parameter(ValueFromRemainingArguments=$true)]
[string[]]$InnerArgs
)
C:\Full\Path\To\git.exe $InnerArgs
} -ErrorAction SilentlyContinue -ErrorVariable fail @Arguments
if ($fail) {
$fail.Exception
}
}
# Could shorten the function name. I instead alias it, for terseness.
Set-Alias -Name git -Value Invoke-Git
# Also alias the name with the extension, as it is called by some applications this way.
Set-Alias -Name git.exe -Value Invoke-Git
这篇关于从PowerShell脚本中提取时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!