Using Git (and everything else) through PowerShell

After a discussion on Stack Overflow a few days ago (and hopefully a useful answer), I got to thinking a bit about how I use PowerShell. It may be a bit geekish, but PowerShell starts up on Windows startup for me. The prompt is almost always open on a second monitor–ready for whatever task I may need.

As the SO post mentioned, I also use PowerShell to connect to my Git repositories. At the office, it has a few more customizations to hashout against our *shudder* SourceSafe */shudder* repositories, but that’s a different post.

For now, I wanted to walk through how profile script is setup in a bit more detail than the SO post.

A profile script is essentially a “startup” script for your PowerShell environment.

By default (perhaps a registry key changes this), it’s located in %userprofile%\Documents\WindowsPowerShell and is aptly named Microsoft.PowerShell_Profile.ps1. The naming convention between “WindowsPowerShell” and “MicrosoftPowerShell” is a bit annoying, but not a big problem.

The file is just plain text, so feel free to use your editor of choice or PowerShell ISE (Windows 7, Windows 2008 R2) for some fancy content highlighting.

What goes in here?

As far as I can tell, the profile is a great place to initialize global customizations:

environmental variables,

paths,

aliases,

functions that you don’t want extracted to .ps1 files,

customizatons to the console window,

and, most importantly, customize the command prompt.

The Console

I use Console2 rather than the standard PowerShell prompt. Console2 is an amazing open source alternative to the standard console and includes features such as ClearType, multiple tabs, and more. Check it out.

I also use Live Mesh, so there are a few things that are unnecessary for most users. Live Mesh is an online syncronization service… so my PowerShell scripts (amongst other things) stay synced between my home and work environments.

Preparing the Environment

My profile script starts off by setting up a few global variables to paths. I use a quick function to setup the parameters based on the computer I’m currently using.

Easy enough. I’m sure I could optimize this a bit more, but it works. Again, this wouldn’t be necessary on a single computer, but since I use LiveMesh and the same PowerShell profile on multiple computers—this keeps my paths in check.

The second step is to modify the $PATH environmental variable to point to my scripts and Git as well as add a new $HOME variable to satisfy Git’s needs.

The ‘prompt’ function overrides how the command prompt is generated and allows a great deal of customization. As I mentioned in the SO post, the inspiration for my Git prompt comes from this blog post.

I’ve added quite a few code comments in here for reference.

function prompt {

Write-Host(“”)

$status_string = “”

# check to see if this is a directory containing a symbolic reference,

# fails (gracefully) on non-git repos.

$symbolicref = git symbolic-ref HEAD

if($symbolicref-ne$NULL) {

# if a symbolic reference exists, snag the last bit as our

# branch name. eg “[master]”

$status_string += “GIT [“ + `

$symbolicref.substring($symbolicref.LastIndexOf(“/”) +1) + “] “

# grab the differences in this branch

$differences = (git diff-index —name-status HEAD)

# use a regular expression to count up the differences.

# M`t, A`t, and D`t refer to M {tab}, etc.

$git_update_count = [regex]::matches($differences, “M`t”).count

$git_create_count = [regex]::matches($differences, “A`t”).count

$git_delete_count = [regex]::matches($differences, “D`t”).count

# place those variables into our string.

$status_string += “c:” + $git_create_count + `

” u:” + $git_update_count + `

” d:” + $git_delete_count + ” | “

}

else {

# Not in a Git environment, must be PowerShell!

$status_string = “PS “

}

# write out the status_string with the approprate color.

# prompt is done!

if ($status_string.StartsWith(“GIT”)) {

Write-Host ($status_string + $(get-location) + “>”) `

–nonewline –foregroundcolor yellow

}

else {

Write-Host ($status_string + $(get-location) + “>”) `

–nonewline –foregroundcolor green

}

return” “

}

The prompts are then color coded, so I can keep track of where I am (as if the really long prompt didn’t give it away).

Now, with our prompts and our pathing setup to our Git directory, we have all the advantages of Git—in a stellar PowerShell package.

NOTE: I would like to point out that I use PortableGit, not the installed variety. Since Git also moves back and forth across my Live Mesh, it seemed more reasonable to use the Portable version. I don’t believe; however, there would be a difference as long as the \bin directory is referenced.

Setting up Aliases—The Easy Way

Brad Wilson’s implementation of find-to-set-alias is brillant. Snag the script and get ready for aliasing the easy way. I keep my most common tools aliased—Visual Studio, PowerShell ISE, and NotePad. I mean, is there anything else? (Well, yes, but I have Launchy for that).

Using find-to-set-alias is easy—provide a location, an executable, and an alias name:

After getting tired of loading up System.Reflection.Assembly everytime I wanted to see what version of a library I had, I came up with a quick script that dumps out the name of the assembly and the file version.

param(

$file= $(throw “An assembly file name is required.”)

)

$fullpath = (Get-Item$file).FullName

$assembly = [System.Reflection.Assembly]::Loadfile($fullpath)

# Get name, version and display the results

$name = $assembly.GetName()

$version =$name.version

“{0} [{1}]” –f$name.name, $version

With this, running assembly-info NHibernate.dll returns:

NHibernate [2.1.0.4000]

Nifty.

Taking it a step further, I created a quick function in my profile called ‘aia’ or ‘assembly info all’ that runs assembly-info on all .dlls in the directory.

Yeah, unfortunately WordPress doesn’t always dump out exactly what I send via BlogJet. Thanks for the heads up! Here’s an update: The full source is now out on codepaste.net: http://codepaste.net/53a7z6

Riku

October 20, 2009 at 9:43 am

Leaving out a few lines from your excellent profile script, I have this running with PowerShell 1.0, Console2, and Git (not portable). It seems “gitk” is a shell script (bash) and will not work out of the box with this solution.

For WinXP (English) users it may be nice to know that the script goes to “C:\Documents and Settings\(Username)\My Documents\WindowsPowerShell\profile.ps1”.

For all: To make it work with Console2, create a new tab in the “Console Settings” (Edit|Settings|Tabs). Point the “shell” field to your PowerShell executable. Then start the new tab (File|New tab) and enjoy!