git clone
将其输出写入stderr
,记录为here。我可以使用以下命令重定向它:
git clone https://myrepo c:\repo 2>&1
但是,这会将所有输出(包括错误)从stderr
重定向到stdout
。有没有办法将进度消息重定向到stdout
,但仍有错误消息写入stderr
。
答案 0 :(得分:7)
MingW更新提供了一种使用Git 2.15.x / 2.16(2018年第一季度)处理重定向的新方法
commit b2f5571点击commit 1a172e4,commit 3f94442,Johannes Schindelin (dscho
)(2017年11月1日)。{
(Junio C Hamano -- gitster
--于2017年11月9日commit 421f21c合并)
mingw
:添加实验性功能以重定向标准句柄特别是在从应用程序(如Visual Studio的团队资源管理器)调用Git时,正确关闭stdin / stdout / stderr非常重要。
但是,当在Windows上生成进程时,如果我们想要使用它们,那些句柄必须被标记为可继承,但是该标志是一个全局标志,并且很可能被其他生成的进程使用,然后这些进程不知道要关闭这些句柄。 / p>让我们介绍一组环境变量(
GIT_REDIRECT_STDIN
和朋友),它们指定文件的路径,甚至更好的命名管道(类似于Unix套接字),并由生成的Git进程使用。登记/> 这有助于解决上述问题:这些命名管道将在启动时以不可继承的方式打开,并且不会传递任何句柄(因此任何生成的子项都不需要关闭继承的句柄)。自v2.11.0(2)以来,Git for Windows附带此功能(标记为实验性),因此在此期间已经看到了一些严重的测试。
Git documentation现在包括:
GIT_REDIRECT_STDIN:
GIT_REDIRECT_STDOUT:
GIT_REDIRECT_STDERR:
仅限Windows:允许将标准输入/输出/错误句柄重定向到环境变量指定的路径。 这在多线程应用程序中特别有用,在这些应用程序中,通过
CreateProcess()
传递标准句柄的规范方法不是一种选择,因为它需要将句柄标记为可继承(因此每个生成的进程会继承它们,可能会阻止常规的Git操作)。主要用途是使用命名管道进行通信(例如
\\.\pipe\my-git-stdin-123
)。
它补充道:
重定向stderr / stdout
mingw
:可选择通过相同的句柄Powershell和Unix shell中的“
2>&1
”符号表示stderr
被重定向到已写入stdout
的同一句柄。让我们使用这个特殊值来允许与
GIT_REDIRECT_STDERR
和GIT_REDIRECT_STDOUT
相同的技巧:如果前者的值是2>&1
,然后将stderr
简单地写入与stdout
相同的句柄。Jeff Hostetler建议使用该功能。
答案 1 :(得分:5)
我使用这个脚本来运行git命令。由于git即使成功也会写入stderr(例如同步时拉取),这会处理这些情况并写出输出的第一行,这通常是你需要知道的。
<#
.Synopsis
Invoke git, handling its quirky stderr that isn't error
.Outputs
Git messages, and lastly the exit code
.Example
Invoke-Git push
.Example
Invoke-Git "add ."
#>
function Invoke-Git
{
param(
[Parameter(Mandatory)]
[string] $Command )
try {
$exit = 0
$path = [System.IO.Path]::GetTempFileName()
Invoke-Expression "git $Command 2> $path"
$exit = $LASTEXITCODE
if ( $exit -gt 0 )
{
Write-Error (Get-Content $path).ToString()
}
else
{
Get-Content $path | Select-Object -First 1
}
$exit
}
catch
{
Write-Host "Error: $_`n$($_.ScriptStackTrace)"
}
finally
{
if ( Test-Path $path )
{
Remove-Item $path
}
}
}
答案 2 :(得分:3)
你可以摆脱stderr
。
通过此命令:
git clone https://myrepo c:\repo 2>$null
通过这样做,所有stderr
都不会显示。
您无法显示进度并仅丢弃错误。如果命令失败,如果成功stderr
stdout
编辑:
看起来git命令输出总是stderr
,即使该命令仅在Windows上成功。
吨。
答案 3 :(得分:2)
我已经修改了Invoke-Git以更好地满足我的需求。
从我在寻找解决方案时阅读的许多帖子中,我猜有很多人可以使用它。
享受。
该版本将:
<#
.Synopsis
Invoke git, handling its quirky stderr that isn't error
.Outputs
Git messages
.Example
Invoke-Git push
.Example
Invoke-Git "add ."
#>
function Invoke-Git
{
param(
[Parameter(Mandatory)]
[string] $Command )
try {
# I could do this in the main script just once, but then the caller would have to know to do that
# in every script where they use this function.
$old_env = $env:GIT_REDIRECT_STDERR
$env:GIT_REDIRECT_STDERR = '2>&1'
Write-Host -ForegroundColor Green "`nExecuting: git $Command "
$output = Invoke-Expression "git $Command "
if ( $LASTEXITCODE -gt 0 )
{
# note: No catch below (only the try/finally). Let the caller handle the exception.
Throw "Error Encountered executing: 'git $Command '"
}
else
{
# because $output probably has miultiple lines (array of strings), by piping it to write-host we get multiple lines.
$output | Write-Host
}
}
# note: No catch here. Let the caller handle it.
finally
{
$env:GIT_REDIRECT_STDERR = $old_env
}
}
答案 4 :(得分:2)
一般来说:
控制台(终端)应用程序-无论是在Windows还是在类似Unix的平台上-只能使用两个输出流:
因此,您不能也不应该根据stderr输出的存在来推断成功与失败 。
相反,您必须仅依靠应用程序的进程退出代码 :
0
表示 成功 在 PowerShell 中,**进程退出代码反映在自动变量$LASTEXITCODE**
中。
具体 ,这意味着:
鉴于git
的stderr输出行,您无法推断它们是否代表 error 消息或其他类型的非数据信息,例如作为进度或状态消息,git
经常使用。
git
将其stderr输出分类重定向到stdout(通过在PowerShell中将环境变量GIT_REDIRECT_STDERR
设置为字符串2>&1
; $env:GIT_REDIRECT_STDERR = '2>&1'
)不是 help,因为错误消息和进度/状态消息都将发送到那里。 如前所述,您只能从非零退出代码推断失败。
一种务实的方法是要执行以下操作:
# Invoke git and capture both its stdout and stderr streams.
$result = git clone https://myrepo c:\repo 2>&1
# Throw an error, if git indicated failure.
if ($LASTEXITCODE) { Throw "git failed (exit code: $LASTEXITCODE):`n$($result -join "`n")" } #`
# Output the captured result, as an array of strings
$result | % ToString
注意:
| % ToString
确保仅输出 strings ,因为成功将stderr行(通过流2
重定向到(>
)输出流(&1
)包装在System.Management.Automation.ErrorRecord
实例中。
2>&1
可能会有意外的副作用-有关背景信息,请参见this answer。
this RFC draft的主题是将外部程序调用更好地集成到PowerShell的错误处理中,尤其是当遇到非零退出代码时,可以选择自动中止执行。
答案 5 :(得分:2)
我只是想补充一下,如果像我一样,您更关心在stderr中出现错误和仅错误,并且不关心任何一种进展,那么有一个非常简单的解决方法-您可以在命令中添加--quiet(或-q)。
这告诉git完全停止报告进度,除非出现 actual 错误。
答案 6 :(得分:0)
这是另一种可能成为某些人灵感的方法。正如其他人指出的那样,重定向和检查退出代码效果很好。与其他答案不同的地方:
-C
而不是cd进入目录一样,但也支持通常不具有该功能的命令。因此,您可以执行igit -dir some/path stash
。我主要在自动脚本中使用它,否则不得不将CD插入目录会很烦人。igit checkout master
的工作方式类似于igit 'checkout master'
。几乎就是因为标准PS警告适用:引用,因此如果需要将引号传递给基础命令,则仍需要一个实际的字符串,即igit log
'-format =“%h%d”'{{ 1}} igit push -v . And PS doesn't require you to type full parameter names meaning
igit push -Verbose will be interpreted as
-v instead of passing
igit-强制-v`或写引号。代码:
i.e. verbose push to git. Use double dash to deal with that