Git output not being captured by Powershell transcript

The intended usage of the tool is for PowerShell host applications, which includes PowerShell itself. As for a solution, there is no clear explanation for the issue at hand, but a workaround has been discovered. There are three possible sources of the problem: powershell, psake, and git. Psake has been eliminated as a suspect by invoking git directly from PowerShell. All other command-line tools function correctly when called from PowerShell, ruling out PowerShell as the source. The issue may be related to how git outputs messages to the console. The next step is to reach out to the PowerShell team to find a permanent solution.


Solution 1:

Instead of calling

Out-Default

, simply utilize your

git

command without modification, and your issue will be resolved by transcribing both its stdout and stderr streams.

By default,

git

writes the status information to stderr. However, using

Out-Default

incorrectly affects the output specifically for stderr, as explained in the bottom section.

The transcript captures the output of both stdout and stderr from external programs, as shown in the following example.

$file = [IO.Path]::GetTempFileName()
"--- DIRECT OUTPUT ---`n"
Start-Transcript $file
# Execute a command that produces
# both stdout and stderr output.
# Do NOT use Out-Default.
if ($env:OS -eq 'Windows_NT') {  # Windows
  cmd /c 'echo hi & nosuch'
} else {                         # macOS, Linux
  sh -c 'echo hi; nosuch'
}
Stop-Transcript
"`n--- CORE CONTENT OF TRANSCRIPT ---"
# Print the core of the transcript.
((Get-Content -Raw $file) -split '(?m)^*+s*$')[2]
Remove-Item $file

On a Windows system, an illustration is presented to indicate that both streams have been recorded.

--- DIRECT OUTPUT ---
Transcript started, output file is C:UsersjdoeAppDataLocalTemptmp342C.tmp
hi
'nosuch' is not recognized as an internal or external command,
operable program or batch file.
Transcript stopped, output file is C:UsersjdoeAppDataLocalTemptmp342C.tmp
--- CORE CONTENT OF TRANSCRIPT ---
Transcript started, output file is C:UsersjdoeAppDataLocalTemptmp342C.tmp
hi
'nosuch' is not recognized as an internal or external command,
operable program or batch file.

The purpose of the

Out-Default

cmdlet:

The function labeled

Out-Default

is intended for internal use only and should not be invoked by user code.

The tool is intended solely for use by PowerShell host applications, including PowerShell. It generates visually appealing string representations of output objects through the use of PowerShell’s output-formatting system, which are subsequently transmitted to the host for presentation.

The cmdlet is made public to permit the override for specifying a personalized output formatter, which is an uncommon practice.

To override a function, you can define a more advanced function with the same parameter declarations and pipeline-binding behavior in your session. A proxy function can help you scaffold such a function, as shown in the bottom section of this answer. Keep in mind that to display output from your function, you need to send the custom-formatted strings to either the original function or use host APIs to print them (which is the simplest approach).


Bug:

Despite being a poor choice, it could be argued that

Out-Default

was still effective in your usage.

Although it is irrelevant for

Out-Default

, which should not be directly invoked,

Out-Host

suffers from the same issue (as of PowerShell Core 7.0.0-preview.6). Nonetheless, there are valid justifications to utilize

Out-Host

specifically for displaying information on the screen without altering transcription behavior.

In particular, the utilization of

Out-Host

directly leads to an issue where any error messages produced by external programs are not logged in the transcript, unlike PowerShell commands which do not encounter this problem.

The issue has been brought to attention in GitHub’s #11134 issue.


Solution 2:


Upon reviewing my original code, I realized that my mistake was leaving the

Out-Default

in it. This caused a bug in

Out-Default

that only affected

stderr

. However, after removing the

Out-Default

, my script was fixed and it successfully transcribed git output.


I was guided in the correct path by an informative link shared by @VonC.

Simply add the environment variable

GIT_REDIRECT_STDERR

with the corresponding value of

2>&1

to the User environment variables in Windows.

Windows users can make use of a handy PowerShell command to include the environment variable.

[System.Environment]::SetEnvironmentVariable("GIT_REDIRECT_STDERR", "2>&1", "User")

Here is a glimpse of my updated transcript.

**********************
Windows PowerShell transcript start
Start time: 20191119165056
Username: 
RunAs User: 
Configuration Name: 
Machine: 
Host Application: C:WindowsSystem32WindowsPowerShellv1.0powershell.exe
Process ID: 16440
PSVersion: 5.1.17134.858
PSEdition: Desktop
PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17134.858
BuildVersion: 10.0.17134.858
CLRVersion: 4.0.30319.42000
WSManStackVersion: 3.0
PSRemotingProtocolVersion: 2.3
SerializationVersion: 1.1.0.1
**********************
Transcript started, output file is .PSTranscript_20191119_165056.txt
Cloning into bare repository 'repo'...
remote: Counting objects: 58975, done.
remote: Compressing objects: 100% (21457/21457), done.
remote: Total 58975 (delta 43347), reused 51727 (delta 37145)
Receiving objects: 100% (58975/58975), 70.33 MiB | 6.04 MiB/s, done.
Resolving deltas: 100% (43347/43347), done.
**********************
Windows PowerShell transcript end
End time: 20191119165115
**********************


Solution 3:


The

Start-Transcript

function should be able to record all console output, regardless of the stream it is being written to. Nonetheless, I observed that when I use

Out-Default

to pipe a git command, no data is recorded in the transcript for that command, despite being displayed in the console.

The reason behind this occurrence is unclear to me, but if you eliminate

| Out-Default

from your clone command, the output will be recorded in the transcript.

Frequently Asked Questions

Posted in Git