My Git, Mercurial and Powershell setup

I’ve been using both Git and Mercurial for a while and I’ve been fine with the standard command line tools for both. Last year, prompted by a co-worker, I started to look at using alternative consoles on Windows. I tried using just a standard Powershell prompt and that worked for a while, but I wanted a little bit more power and configuration. So I looked at Console2 and ConEmu. I’ve settled on ConEmu starting a Powershell prompt for now, but I wanted to focus on how I customize the Powershell prompt, and my .gitconfig, to allow me to work more efficiently with Git and Mercurial.

First I looked into custom Git prompts, I started with Posh-Git. Kieth has done a wonderful job creating a custom Powershell prompt, as well as enhancing the overall Git experience through tab completion. I personally found it to be too slow on most of the repos I work with so I ditched it (for now). If you like posh-git, I’d recommend these two posts by Phil Haack as excellent starting points for installing and configuring posh-git.

I’ve been using the combined Mercurial and Git Powershell prompt written by Matthew Manela and I really like it. I like the way it displays un-staged changes better than posh-git and it’s been really fast no matter how large the repository. The only line I added to my Powershell profile is a call to load the Visual Studio Environment vars.

cmd /c """C:\Program Files `(x86`)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat""" ""x86""

I mentioned that I use Git a lot at work, well that’s half-true. I use the Git-SVN bridge a lot at work. It allows me the flexibility to create local branches, but still lets me connect to my groups SVN repository. Someday, we’ll move to a full Git repository but we just moved a lot of developers off of TFS and onto Subversion and we want to wait a little while to shake up their entire world again. I use a lot of custom aliases in my .gitconfig and set up a global .gitexcludes file.

[alias]
    aa = add --all .
    st = status
    br = branch
    cl = clone
    co = checkout
    ci = commit
    sr = svn rebase
    sci = svn dcommit
    fu = reset --hard
    lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --
    pu = !"git fetch origin -v; git fetch upstream -v; git merge upstream/master"
[merge]
	tool = kdiff3
[core]
    autocrlf = True
    excludesfile = "~/.gitexcludes"
[diff]
	guitool = kdiff3
[difftool "kdiff3"]
    path = "C:/Program Files (x86)/KDiff3/kdiff3.exe"
[mergetool "kdiff3"]
	path = "C:/Program Files (x86)/KDiff3/kdiff3.exe"
[svn]
	rmdir = true

Most of the aliases are self-explanatory and are pretty common in .gitconfig files. The two most useful aliases I have in that file are the “pu” and the “fu” aliases.

git fu – Does a hard reset, effectively dumping all of my changes and putting me back at the HEAD.
git pu – Does a pull request from my origin repo, then the upstream remote repo, and finally merges the two together. It’s a handy shortcut for getting my forks up to speed.

*.DS_Store
*.idea
*.dbmdl
*.user
*.suo
*.cache
*.log
*.log.*
[Oo]bj
[Bb]in
ErrorLogs
*~
*.swp
_ReSharper*
*.db
*.orig
*.rej
*.vs10x
CI
*.docstates

That is the contents of my .gitexcludes file. It covers most of the usual suspects I’ve run into. The “CI” blocker is custom to our work environment, that’s where our Continuous Integration builds end up when you run our build script. and .DS_Store is a blight on humanity that Apple needs to eradicate. There is a work-around for network drives at least. But if you plug in a USB drive, OSX will still create the .DS_Store directories on them and the work around will not erase existing .DS_Store directories on network shares.

I haven’t set up any aliases in my Mercurial config, I haven’t really found the need to. I find the Mercurial commands to be much more intuitive and easier to remember than the Git commands. Mostly because “Git hates developers

* I’ve hesitated writing this for a while because I may seem negative about a very popular Powershell module for Git called PoshGit. I understand that it works well for some people, and it has gotten faster since I first used it, but it still is too slow for my daily usage at work. I used it at home for a while, but I started to notice the LARGE pauses more and more when I would enter a Git directory when using PoshGit. So I switched to the module I talk about above. There is a way around the prompt performance issues on a per-repo basis. But if I have to turn off the custom prompt completely, posh-git looses some of it’s appeal to me. We had Keith, and some other Git folk, on the podcast to discuss the entire Git on Windows situation a while back and included a discussion of posh-git.

  • http://HuddledMasses.org Joel “Jaykul” Bennett

    That call to cmd isn’t going to import the environment into your powershell profile. It’ll run and then finish, and you still won’t have the environment. You should try Import-CmdEnvironment http://poshcode.org/3547

  • cromwellryan

    I use this for getting a vsvars environment setup.  I don’t have VS on every environment that I have Powershell, but you could easily call the vsvars32 funciton during load.  Might try jayjul’s version though.
    https://github.com/cromwellryan/ps-config/blob/master/vsvars.ps1 

    There are a lot of other powershell goodies in the profile as a whole, including creating gists (psgist module) and start-host for quick iisexpress hosting of a directory.

  • http://d.moonfire.us/ D. Moonfire

    I had a *lot* of trouble with Posh when it came to speed. Eventually I found that setting the following made a very big different at the expense of having the file counts. But, I still got all of the parts I use (tab-completion, a partial prompt with branch and mode) without the long pauses.

    $global:GitPromptSettings.EnableFileStatus = $false

    But, your stuff looks pretty interesting and I’ll have to check it out.