'Behavior of bat and Powershell is different when clicked vs run from respective consoles, specifically with git

This post appears wordy, but there's actually not much here to read. Just figured more details > less details.

I am working on some tools to speed up my git workflow. I found/modified a PowerShell script that attempts to update all git branches:

function PullAllBranches() {
$branches = git branch
foreach($branch in $branches){
    $fixedBranch = $branch.Substring(2, $branch.Length - 2) # extract actual name
    $trackedExpression = "branch." + $fixedBranch + ".merge"
    $trackedBranch = git config --get $trackedExpression # returns refs/heads/master (?)
 #  Write-Host($trackedBranch)
    if(![string]::IsNullOrEmpty($trackedBranch))
    {
        Write-Host('Pulling branch: ' + $fixedBranch)
        git checkout "$fixedBranch" | Out-Null # Pipe to stdout
        git pull 
    }
    else {
        Write-Host('Branch "' + $fixedBranch + '" has no tracked remote')
    }
}
}

PullAllBranches

Read-Host -Prompt "Press Enter to exit"

It fails saying the repo does not exist:

Pulling branch: master
git : Switched to branch 'master'
At C:\Users\username\Git\username\csv-plottr\pull_updates.ps1:15 char:9
+         git checkout "$fixedBranch" | Out-Null # Pipe to stdout
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Switched to branch 'master':String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

git : Unable to open connection:
At C:\Users\username\Git\username\csv-plottr\pull_updates.ps1:16 char:9
+         git pull
+         ~~~~~~~~
    + CategoryInfo          : NotSpecified: (Unable to open connection::String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

Host does not exist
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

However, stepping through the code, appears it should work. Digging into this, I tried a simple git pull origin master in PowerShell CLI:

PS C:\Users\username\Git\username\csv-plottr> git pull origin master
From gh-gitlab:username/csv-plottr
 * branch            master     -> FETCH_HEAD
Already up to date.
PS C:\Users\username\Git\username\csv-plottr>

Where 'gh-gitlab' is a SSH identity pointing to a gitlab server on my LAN(equivalent to 10.0.0.xxx:username/csv-plottr). This approach works fine, making me think running a PowerShell script executes in a different environment when run from PowerShell ISE or something than typing into the CLI. I printed working directory in both cases and it is the same. Are there any PowerShell/Windows with more experience than I have who could shed some light or point me in the right direction on google?

Curiously, I tried the same thing in a batch file, what I am trying to get away from using, with similar results. From cmd:

C:\Users\username\Git\username\csv-plottr>git pull origin master
From gh-gitlab:username/csv-plottr
 * branch            master     -> FETCH_HEAD
Already up to date.

And from the batch file merely containing:

git pull origin master
pause

Running by double clicking, I get:

C:\Users\username\Git\username\csv-plottr>git pull origin master
Unable to open connection:
Host does not existfatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

C:\Users\username\Git\username\csv-plottr>pause
Press any key to continue . . .

But CDing to the directory and running it by typing the name of the script gives:

C:\Users\username\Git\username\csv-plottr>.\pull_updates.bat

C:\Users\username\Git\username\csv-plottr>git pull origin master
From gh-gitlab:username/csv-plottr
 * branch            master     -> FETCH_HEAD
Already up to date.

C:\Users\username\Git\username\csv-plottr>pause
Press any key to continue . . .

success! It says the repo is up to date in this case.

What gives??? Why is this behavior different and what could I do (or google about) to create the same behavior? I echo'd %CD% (pwd) and it checks out. I have fought this all day, and finally figured I'd ask for help with what I thought would be a 15 minute job. I'm stumped. Thanks in advance.


Edit for /u/mklement0:

I wanted double click functionality for powershell, so I set this registry key: HKCR\Microsoft.PowerShellScript.1\Shell\Open\Command

to

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -ExecutionPolicy unrestricted -File "%1"%*

Which fixes both troubles with running powershell and execution policy, and convenience of just double clicking. As best I can tell, this should be identical to going into a powershell window, CDing to the correct dir, and calling your ps1 script.

But when double clicking my ps1 script I get the same issues:

Pulling branch: dev
Switched to branch 'dev'
Unable to open connection:
Host does not existfatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
Pulling branch: master
Switched to branch 'master'
Unable to open connection:
Host does not existfatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
Press Enter to exit:

vs calling from a PS console:

PS C:\Users\username\Git\username\csv-plottr> .\pull_updates.ps1
Pulling branch: dev
Switched to branch 'dev'
Already up to date.
Pulling branch: master
Switched to branch 'master'
Already up to date.
Press Enter to exit:

success!

This happens with batch files too. This was not done in the PowerShell ISE either, just to rule that out.



Solution 1:[1]

Do not use the PowerShell ISE to run your scripts (for development, it may be OK, but you should know the pitfalls):

  • The ISE's PowerShell host is not a true console and behaves differently, which is likely the problem in this case (see below).

  • All code invocations run in the same session, via dot-sourcing, so that actions of previous invocations can affect subsequent invocations.

Specifically, the ISE reports a (non-terminating) error whenever an external program such as git writes to stderr, even though that may not indicate an actual error (external utilities write any non-data messages, such as status information, to stderr); only an external program's exit code - reflected in $LASTEXITCODE in PowerShell - truly signals success vs. failure.

Note, however, that despite the error "noise", execution continues, unless you've set $ErrorActionPreference to 'Stop'.

Example:

cmd /c 'echo hi >&2'

The above prints 'hi' normally in the regular console, but presents like an error in the ISE.


Generally, consider switching from the ISE to Visual Studio Code and its PowerShell extension:

  • all future development effort will focus there
  • it doesn't exhibit the problematic behavior at hand

However, note that, as in the ISE, all code runs dot-sourced in the same session by default, which, as stated, has potentially unwanted side effects when running code repeatedly.

To avoid that, use setting "powershell.debugging.createTemporaryIntegratedConsole": true to create a temporary session for debugging (add it to settings.json via >Preferences: Open Settings, or check setting PowerShell > Debugging: Create Temporary Console in the settings dialog) - see this answer for the behavioral implications.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1