15

In PowerShell, git checkout runs without any error message. In the ISE, while git checkout stills works, the ISE gives an error message.

> git checkout master
Your branch is ahead of 'origin/master' by 3 commits.
(use "git push" to publish your local commits)
git : Switched to branch 'master'
At line:1 char:1
+ git checkout master
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Switched to branch 'master':String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

This isn't a major problem, because git checkout still works. It's annoying, though, so I'd like to know why the ISE complains when the standard PowerShell doesn't, and importantly, how can we prevent this annoyance.

I have looked at Why is Powershell ISE showing errors that Powershell console does not show?, which explains that the ISE is just displaying what the normal shell is experiencing. That answer does not explain how to quiet down this annoying behavior.

Community
  • 1
  • 1
Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
  • 1
    it seems ise does react to stderr output where powershell does not, maybe have a look at the answers to this question: http://stackoverflow.com/questions/1394084/ignoring-an-errorlevel-0-in-windows-powershell If you dont want the error to be shown you can redirect stderr to $null like this `2> $null` – Paul Nov 11 '14 at 19:04
  • Should/Could this question be re-written to represent the fact that because Git uses the error output stream for much of its output (not just for checkout), it looks terrible in any host (not just the ISE)? – Nathan Hartley Jul 21 '16 at 15:57

4 Answers4

10

There are few ways you can avoid these errors, none of them looks or feels 'natural'. First one uses error stream redirection and some logic around errors:

$out = git ? 2>&1
if ($?) {
    $out
} else {
    $out.Exception
}

Second depends on the ErrorAction, that is available only for PowerShell constructs, so we need to build one first:

& {
    [CmdletBinding()]
    param()

    git ?
} -ErrorAction SilentlyContinue -ErrorVariable fail

if ($fail) {
    $fail.Exception
}

In my ISEGit module I use latter to avoid error records 'leaking' to end user in uncontrolled manner.

Finally you can 'fix it' (well, sort off...) by making sure you can a string in the end:

"$(git ? 2>&1 )"

Or something I would vote against as it will leave you unaware of any actual errors, setting global $ErrorActionPreference to SilentlyContinue - though this is not different from redirecting error stream to $null.

BartekB
  • 8,492
  • 32
  • 33
8

As specified here, adding -q after the command for quietness won't show these kind of errors.

user7291698
  • 1,972
  • 2
  • 15
  • 30
Ali Ben Zarrouk
  • 1,891
  • 16
  • 24
6

It looks like you can now redirect stderr to stdout throughout your powershell script by simply setting an environment variable:

$env:GIT_REDIRECT_STDERR = '2>&1'
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
3

A profile ready Function-ized version of @BartekB's excellent answer...

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
Nathan Hartley
  • 4,005
  • 2
  • 43
  • 46
  • In addition I added `Function git() { Invoke-Git @args }` so I can use `git` normally. – BrunoLM May 18 '17 at 14:07
  • 1
    Could rename the function or alias it. I'll add the alias line to the script example. – Nathan Hartley May 18 '17 at 19:22
  • Creating an alias for `git.exe` causes an infinite loop (because on your `Invoke-Git` you use it). Aliasing just `git` is fine and doesn't cause issues. – BrunoLM May 19 '17 at 11:51
  • 1
    Ha! Good catch. That doesn't happen in my profile, because I use the full path to Git within the function. I'll suggest the same here. – Nathan Hartley May 19 '17 at 15:54
  • 1
    @NathanHartley You should add that in ISE you still have to check `$LASTEXITCODE` after the call to `Invoke-Git`. For example for me, in a git clone in ISE the fail variable was never empty after a clone (although it worked) but `$LASTEXITCODE` was `0` so fail could be ignored. I was able to fix it by doing this as the last check `if ($LASTEXITCODE -ne 0 -and $fail) { throw $fail.Exception }`. This way I can throw the real git errors – MonkeyDreamzzz Aug 25 '17 at 07:55