The goal of this blog article is to configure the PowerShell ISE (Integrated Scripting Environment) so the management of Git version control can be performed from it. Most tutorials you’ll find will attempt to lead you down the path of using SSH instead of HTTPS to synchronize your repositories to GitHub from the command-line but that’s really over-complicated and unnecessary if you’re using a Windows based machine.

The client machine used in this blog article runs the 64 bit version of Windows 10 Enterprise Edition. Windows 10 has PowerShell version 5 installed by default. Git for Windows version 2.7.0 and Posh-Git version 0.5.0.2015 are the third party software versions used in this blog article.

The first question you may ask is why not just use the Git Shell that’s installed as part of GitHub Desktop? While it’s true that you can launch Git Shell and then the ISE from it, the problem is that Git Shell uses the x86 (32 bit) version of PowerShell on a machine with a 64 bit operating system which means you won’t have all of your PowerShell modules available and that’s a solution that ends up being a sub-par experience. What I want to accomplish is simple, to launch a PowerShell ISE session as I always do and then to be able to manage both local Git repositories as well as remote ones on GitHub.

If you’ve installed GitHub Desktop, then you already have a copy of the Posh-Git PowerShell module and a portable version of Git installed which are located in subfolders of “$env:LOCALAPPDATA\GitHub” in your user’s profile. I chose not to use those versions and to go ahead and install them for all users in the program files folder since I’m running PowerShell elevated as an alternate user (I login to Windows as a standard user and run PowerShell elevated as a local admin). You could also manage your GitHub repositories using this process without ever having to install GitHub Desktop.

First, install and configure Git for Windows. I previously covered this topic in another blog article. In this scenario, I ran the Git installer elevated so I could install it in the program files folder and I took the option to add the path for Git to the system environment variable path:

Make sure that you’ve configured Git as the user who is running PowerShell (I ran these commands from within my elevated PowerShell session):

git config --global user.name 'your name' git config --global user.email 'your email address' git config --global push.default simple 1 2 3 git config -- global user . name 'your name' git config -- global user . email 'your email address' git config -- global push . default simple

I used my private GitHub email address instead of my personal public email address to eliminate the possibility of spam. For more information on this topic, see the GitHub help article on “Keeping your email address private“.

Install the Posh-Git PowerShell module from the PowerShell Gallery:

Install-Module -Name posh-git -Force Get-Module -Name posh-git -ListAvailable 1 2 Install-Module -Name posh -git -Force Get-Module -Name posh -git -ListAvailable

I created a custom profile script that changes my PowerShell prompt depending on whether or not I’m in a directory that’s part of a Git repository. There is a default profile located in the Posh-Git module folder, but I chose not to use it for a number of reasons, one of which is that I wanted to retain the ability to show a nested prompt and I also wanted the prompt to look similar to Git Bash when working with a Git repository. The one in the Posh-Git folder also generates an error because it attempts to setup an SSH agent which is not available in the version of Posh-Git that’s installed from the PowerShell Gallery. See the version on GitHub if that’s something you’re interested in, but as you’ll learn in this blog article, the SSH agent is unnecessary.

I setup this profile to run for all users and all hosts on my machine since I often run PowerShell as an alternate user and I want it to be available from the PowerShell console and ISE:

profile.ps1 Set-Location -Path $env:SystemDrive\ Clear-Host $Error.Clear() Import-Module -Name posh-git -ErrorAction SilentlyContinue if (-not($Error[0])) { $DefaultTitle = $Host.UI.RawUI.WindowTitle $GitPromptSettings.BeforeText = '(' $GitPromptSettings.BeforeForegroundColor = [ConsoleColor]::Cyan $GitPromptSettings.AfterText = ')' $GitPromptSettings.AfterForegroundColor = [ConsoleColor]::Cyan function prompt { if (-not(Get-GitDirectory)) { $Host.UI.RawUI.WindowTitle = $DefaultTitle "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) " } else { $realLASTEXITCODE = $LASTEXITCODE Write-Host 'PS ' -ForegroundColor Green -NoNewline Write-Host "$($executionContext.SessionState.Path.CurrentLocation) " -ForegroundColor Yellow -NoNewline Write-VcsStatus $LASTEXITCODE = $realLASTEXITCODE return "`n$('$' * ($nestedPromptLevel + 1)) " } } } else { Write-Warning -Message 'Unable to load the Posh-Git PowerShell Module' } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Set-Location -Path $env : SystemDrive \ Clear -Host $Error . Clear ( ) Import-Module -Name posh -git -ErrorAction SilentlyContinue if ( -not ( $Error [ 0 ] ) ) { $DefaultTitle = $Host . UI . RawUI . WindowTitle $GitPromptSettings . BeforeText = '(' $GitPromptSettings . BeforeForegroundColor = [ ConsoleColor ] :: Cyan $GitPromptSettings . AfterText = ')' $GitPromptSettings . AfterForegroundColor = [ ConsoleColor ] :: Cyan function prompt { if ( -not ( Get-GitDirectory ) ) { $Host . UI . RawUI . WindowTitle = $DefaultTitle "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) " } else { $realLASTEXITCODE = $LASTEXITCODE Write-Host 'PS ' -ForegroundColor Green -NoNewline Write-Host "$($executionContext.SessionState.Path.CurrentLocation) " -ForegroundColor Yellow -NoNewline Write -VcsStatus $LASTEXITCODE = $realLASTEXITCODE return "`n$('$' * ($nestedPromptLevel + 1)) " } } } else { Write-Warning -Message 'Unable to load the Posh-Git PowerShell Module' }

The latest version of my profile script can be found in my PowerShell repository on GitHub. That repository is where I keep my PowerShell code I want to share publicly that doesn’t fit into more specific categories. I have dedicated repositories for Active Directory, SQL, etc. If you’re not placing your profile script in source control, why not?

I’ll clone my PowerShell repository from GitHub to my local computer:

git clone https://github.com/mikefrobbins/PowerShell.git PowerShell -q Set-Location -Path .\PowerShell 1 2 git clone https : / / github . com / mikefrobbins / PowerShell . git PowerShell -q Set-Location -Path . \ PowerShell

Notice in the previous example that the prompt changed once I entered the PowerShell folder. That’s because of the custom profile script and this folder being part of a Git repository. If I were to change to another folder that’s not part of a Git repository, my prompt would change back to the default PowerShell one.

Getting the status of this repository shows that it’s up to date with the remote and you can also see the details of where the remote is located on Github:

git status git remote -v 1 2 git status git remote -v

The problem at this point is the ISE generates some weird error message that you’ll find all sorts of suggestions when searching on the Internet for solutions, but unfortunately all of the recommended fixes are a dead-end.

git push 1 git push

git : bash: /dev/tty: No such device or address

At line:1 char:1

+ git push

+ ~~~~~~~~

+ CategoryInfo : NotSpecified: (bash: /dev/tty:…vice or address:String) [], RemoteException

+ FullyQualifiedErrorId : NativeCommandError

error: failed to execute prompt script (exit code 1)

fatal: could not read Username for ‘https://github.com’: Invalid argument

At this point, you need to punt and go back to the PowerShell console to perform a few tasks that will end up resolving the problem that you’re experiencing in the ISE.

Running the same command from the console appears to work, but due to having two-factor authentication enabled on your account, the authentication will fail. Notice that I didn’t say if you have two-factor authentication enabled on your account because in this day and age you better have two-factor authentication enabled or you’re asking to have your account hacked.

git push 1 git push

See this blog article on GitHub to learn more about setting up two-factor authentication on your GitHub account.

Create a “Personal access token” in your GitHub account that will be used for authentication at the command-line:

See this GitHub help topic to learn more about setting up a Personal access token for command-line use. Make sure you read about limiting the scope of this token before continuing. See the GitHub Developer OAuth API documentation to learn more about what each scope option authorizes.

Using the token as the password works without issue except it has to be entered each time a command is run that requires authentication to GitHub:

git push 1 git push

To prevent having to enter the token each time, enable the credentials to be saved to Windows credential manager:

git config --global credential.helper wincred 1 git config -- global credential . helper wincred

For more information about the command used in the previous example, see the “Caching your GitHub password in Git” help topic on GitHub.

The next time the token is entered as the password, it will be saved to Windows credential manager and you’ll no longer be asked for a userid / password combination when running a command that requires authentication to GitHub.

git push git push 1 2 git push git push

Switch back to the ISE. Running the same commands that previously generated the cryptic error message now run without issue. It appears that they generate errors but these are due to Git sending much of its output to StdErr instead of StdOut so they can safely be ignored:

git status git push Set-Location -Path ..\AWS git status git push 1 2 3 4 5 git status git push Set-Location -Path . . \ AWS git status git push

git : Everything up-to-date

At line:1 char:1

+ git push

+ ~~~~~~~~

+ CategoryInfo : NotSpecified: (Everything up-to-date:String) [], RemoteException

+ FullyQualifiedErrorId : NativeCommandError

Notice that in the previous example, you can now push to any of your GitHub repositories without being prompted for authentication. You might be wondering where the saved credentials are stored at? They’re stored securely in Windows credential manager:

cmdkey /list 1 cmdkey / list

Use caution when changing branches and having files from a Git repository working folder open in the ISE. You could unknowingly overwrite files in one branch with files from a different branch. My recommendation is to close any open ISE tabs containing files from a Git repository working folder before switching branches.

You’ll find that you’ll be much more likely to place your PowerShell scripts, functions, and modules in source control now that you can manage the version control system right from the same interface that you’re writing your code in.

Additional GitHub help topics worth mentioning: “Git automation with OAuth tokens” and “Personal API tokens“.

Update 2/20/16

Based on a number of responses I received on Twitter, there are several reasons you might want to use SSH instead of HTTPS. Most of these use cases fall outside of the scope that my blog article was originally intended for, but I still wanted to make you aware of them: (1) You hop between different operating systems, (2) you shuffle between different services such as GitHub, GitLab, and Gogs, (3) you’re using on-premises SSL: “Adding a corporate (or self-signed) certificate authority to git.exe’s store“.

Update 2/21/16

I decided to do a little more research on the subject of which protocol to use for accessing GitHub from Git based on my previous update since those tips came from people in the industry that I have a great deal of respect for. My research lead me to a help page on GitHub on how to “Set Up Git” which is self explanatory:

There are definitely some considerations to keep in mind and reasons you would want to use SSH over HTTPS which is probably why they make it available, but I have a difficult time going against the recommendation to use HTTPS from the software manufacturer considering this blog article focuses specifically on accessing GitHub from Git.

µ

Share this: Twitter

Reddit

LinkedIn

Facebook

Pocket

Print

