git clone
は、ドキュメント化された here として、その出力をstderr
に書き込みます。これを次のコマンドでリダイレクトできます。
git clone https://myrepo c:\repo 2>&1
ただし、これにより、エラーを含むすべての出力がstderr
からstdout
にリダイレクトされます。進捗メッセージをstdout
にリダイレクトする方法はありますが、エラーメッセージがstderr
に書き込まれます。
このスクリプトを使用して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
}
}
}
MingWの更新により、Git 2.15.x/2.16(2018年第1四半期)でリダイレクトを処理する新しい方法が提供されます
commit b2f5571 、 commit 1a172e4 、 commit 3f94442 (2017年11月1日)を参照 Johannes Schindelin(dscho
) によって。
( Junio C Hamanoによってマージ-gitster
- in commit 421f21c 、2017年11月9日)
mingw
:標準のハンドルをリダイレクトする実験的な機能を追加します特に、Visual StudioのチームエクスプローラーなどのアプリケーションからGitを呼び出す場合、stdin/stdout/stderrが適切に閉じられていることが重要です。
ただし、Windowsでプロセスを生成する場合、それらのハンドルを使用する場合は、それらのハンドルを継承可能としてマークする必要がありますが、そのフラグはグローバルフラグであり、他の生成されたプロセスでは使用できない可能性があります。それらのハンドルを閉じます。ファイルまたはさらに良い名前付きパイプ(Unixソケットに類似)へのパスを指定し、生成されたGitプロセスで使用される環境変数(_
GIT_REDIRECT_STDIN
_およびその仲間)のセットを紹介しましょう。
これは、上記の問題を回避するのに役立ちます。これらの名前付きパイプは、起動時に継承不可能な方法で開かれ、ハンドルは渡されません(したがって、継承されたハンドルは、生成された子によって閉じる必要はありません)。 。この機能は、v2.11.0(2)以降、Git for Windows(実験的としてマークされている)に同梱されているため、しばらくの間深刻なテストが行われてきました。
Gitドキュメント に以下が含まれるようになりました:
_GIT_REDIRECT_STDIN:
GIT_REDIRECT_STDOUT:
GIT_REDIRECT_STDERR:
_
Windowsのみ:標準の入力/出力/エラーハンドルを環境変数で指定されたパスにリダイレクトできます。これは、
CreateProcess()
を介して標準ハンドルを渡す正規の方法がオプションではないマルチスレッドアプリケーションで特に役立ちます。これは、ハンドルを継承可能としてマークする必要があるためです(その結果every生成されたプロセスはそれらを継承し、通常のGit操作をブロックする可能性があります)。主な使用目的は、通信に名前付きパイプを使用することです(例:_
\\.\pipe\my-git-stdin-123
_)。
そしてそれは追加します:
mingw
:オプションで、同じハンドルを介してstderr/stdoutをリダイレクトしますPowershellおよびUnixシェルの「_
2>&1
_」表記は、stderr
がstdout
がすでに書き込まれているのと同じハンドルにリダイレクトされることを意味します。この特別な値を使用して、_
GIT_REDIRECT_STDERR
_および_GIT_REDIRECT_STDOUT
_で同じトリックを許可しましょう。前者の値が_2>&1
_の場合、stderr
は単純に同じハンドルに書き込まれますstdout
。この機能はJeff Hostetlerによって提案されました。
使用例:_$env:GIT_REDIRECT_STDERR = '2>&1'
_
stderr
から取り除くことができます。
このコマンドで:
git clone https://myrepo c:\repo 2>$null
そうすることで、すべてのstderr
は表示されなくなります。
進行状況を表示してエラーのみを破棄することはできません。コマンドが失敗した場合、すべての出力はstderr
成功した場合stdout
編集:Windowsでのみコマンドが成功した場合でも、gitコマンドの出力は常にstderr
になるようです。 T.
一般的に話す:
コンソール(ターミナル)アプリケーション-WindowsかUnixライクなプラットフォームかに関係なく-2つの出力ストリームのみが自由に使用できます。
したがって、あなたはできません。また、stderr出力の存在から成功と失敗を推測するべきではありません.
代わりに、アプリケーションのプロセス終了コードのみに依存する必要があります(== --- ==):
0
は、成功PowerShellでは、**プロセスの終了コードが自動変数$LASTEXITCODE**
に反映されます。
具体的には、これは以下を意味します:
与えられたgit
のstderr出力行は、それらがerrorメッセージまたは他の種類の非データ情報、進捗状況やステータスメッセージなど、git
が頻繁に使用します。
git
に指示する(PowerShellで環境変数GIT_REDIRECT_STDERR
を文字列2>&1
; $env:GIT_REDIRECT_STDERR = '2>&1'
に設定することにより)はしないヘルプ。エラーメッセージと進行状況/ステータスメッセージが同様に送信されます。すでに述べたように、ゼロ以外の終了コードからのみ障害を推測する必要があります。
実用的なアプローチは次のことを行うことです:
# 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
stderr行が(ストリーム2
を介して)成功出力に(>
)にリダイレクトされた場合、stringsのみが出力されるようにしますストリーム(&1
)は System.Management.Automation.ErrorRecord
インスタンスにラップされます。
2>&1
には予期しない副作用が生じる可能性があります-背景情報については この答え を参照してください。
PowerShellのエラー処理への外部プログラム呼び出しのより良い統合は、 このRFCドラフト の主題であり、特に、遭遇時に実行を自動的に中止するオプションを持っているゼロ以外の終了コード。
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
}
}