Skip to content

Git & PowerShell Revisited

Since my last post about using Git from within PowerShell, a few things have changed which make the experience even better than before, including some pretty nifty tab completion.

Prompt

The prompt is basically the same idea as the one I previously wrote about, but with several enhancements by Keith Dahlby. It now shows working files and staged files in your index seperately which makes it easier to keep track of exactly where you are. This is especially useful if you actually make proper use of the index. I tend to use Git without really making proper use of it, so the improvements are a bit less relevant to me but even so I have found it useful to have it done this way at times.

Prompt

Working files added/modified/removed are shown in yellow as they previously were, but any changes to the index are shown in blue. These use all the same symbols and conventions as before, so it's still pretty easy to follow. To be honest, I'm not sure why I never thought of doing this myself when I created the original prompt.

Tab Completion

Along with PowerShell's default tab completion where the names of files are automatically filled in on the press of the tab key, we can now utilise this mechanism to make life using Git easier. It can autocomplete the available commands, remotes, branches and so on. And just like PowerShell's default completion, it will narrow down the options according to those letters which have been typed. Jeremy Skinner created the initial version and wrote about it.

The tab completion makes the whole workflow smoother and faster - and cuts down your keystrokes. It has all the features of Jeremy's initial version but also include any aliases you have defined in the command list. For example, typing git <tab> will include your aliases along with the usual checkout, push, pull and so on. Of course to keep things sane, typing git help <tab> will not include your aliases since git won't know how to provide any help on them.

The tab completion also has two different options for which commands to include in the list. By default, it includes all the common ones (those which are shown when you run git help). If this isn't enough for you, you can choose to have it use all the commands (those which are shown when you run git help --all).

Get It

I originally created the prompt and Jeremy Skinner originally created the tab completion (based on a very half-baked start I'd made to work with PowerTab - I have abandoned that now). Both of these were taken by Keith Dahlby and he changed and improved things quite a bit and put it up on GitHub. My version is a fork of his improved version with yet more changes, tweaks and additions.

Installation is a case of grabbing the bits (either clone the repo or use GitHub's download, whatever works for you) and pop them into your PowerShell profile directory. These can be included into your profile.ps1 file (using a nice trick Keith used)...

Push-Location (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent)

# Git utils
. ./GitUtils.ps1
. ./GitPrompt.ps1
. ./GitTabExpansion.ps1

Pop-Location 

...and used from within a prompt function and TabCompletion function in order to provide the functionality.

# Set up a simple prompt, adding the git prompt parts inside git repos
function prompt {
    Write-Host($pwd) -nonewline

    # Git Prompt
    $Global:GitStatus = Get-GitStatus
    Write-GitStatus $GitStatus

    return "> "
}

# Set up tab expansion and include git expansion
function TabExpansion($line, $lastWord) {
    $lastBlock = [regex]::Split($line, '[|;]')[-1]

    switch -regex ($lastBlock) {
        # Execute git tab completion for all git-related commands
        'git (.*)' { GitTabExpansion $lastBlock }
        # OR to include all advanced commands in tab command completion:
        #'git (.*)' { GitTabExpansion $lastBlock $TRUE }
    }
}

# Enable colors on the Git output
Enable-GitColors

This is shown in the profile.example.ps1 file included. Do be aware though that my way of doing this has thrown away some of what Keith did in regards to handling default completion behaviour. Personally, I've found my approach works fine but there are some situations where this may yield sub-optimal behaviour in regards to variable name completion and so on. However, it does make it a lot easier to plug in other tab completion behaviour (for Mercurial for example). Your mileage may vary.

The Future

It is still definitely a work in progress. Only the other day, I upgraded to the latest MSysGit which is now based on Git 1.7, and includes some changes which I'll have to take account of. For now, it's probably best to avoid this on the latest version as it may or may not always work correctly (although all the basics using the default settings should be fine). I have created a 'git1.7' branch which I'm going to fix up before merging back into master. Keith is also actively working on his version (which has some differences to mine - well worth checking out) so I'm going to continue to work with him and share my changes going forward.

In addition, Keith has also set up a Google Group for posh-git. Feel free to join and contribute any ideas or suggestions you have. Enjoy.