DaveWentzel.com            All Things Data


git and Powershell Integration

The power of git is its CLI and scripting abilities.  That of course means it is less-than-friendly for a Windows GUI guy.  

Or is it?  

I was recently trying to automate a simple git script in Windows to automatically do a fetch and merge (I know this is a bad idea, but I had my reasons) for all git repositories on my local machine.  Basically I have a folder tree where I keep my source code with subfolders for each remote repository I connect to...something like the structure on the right.  Most of these repos I use solely for code review purposes and rarely change any of the code, hence why I'm cool with fetch and merge (or pull if you will).  Even in the rare cases where I do want to make changes it is almost always master branch.    

Anytime I want to automate something in Windows I use Powershell.  To manipulate git on Windows requires loading Git Bash from within Powershell using some variant of loading a Bash shell in a DOS shell in a Powershell shell.  Kludgey.  it also makes error-handling unreliable. 

Some simple googling turned up the posh-git Powershell module.  


F'ing awesome module.  

If you ever longed for the day where git used more normal DOS style-syntax, this is the day.  The author was very ingenious.  Instead of creating PoSH commands that wrap git commands (for instance, invoke-gitfetch, or something stupid like that), which would require us to learn another set of git CLI commands, posh-git actually uses the standard git commands.  With tab-completion of commands too.  

When you "cd" into a git-enabled folder your Posh prompt even tells you what branch you are currently on without any extra intervention.  Note the screenshot on the right.  Ignore the error, that's totally unrelated to posh-git...it's something I'm experimenting with.  

Note the extra "stuff" in brackets.  master is the branch.  It's in cyan meaning it's in sync with its remote.  The other options in burgundy indicate the number of files that you have added/modified/removed/conflicted.  It basically did a git status without you having to.  

In any case, I could rave about posh-git for a long time.  Just note that it helps you automate git on Windows.  

Installing posh-git (or any module) Automatically -- Best Practice Pattern

When writing an automation routine it is best to never assume that the host running the script has all of the requisite software installed and environment configured correctly.  You never know when someone will run the script on an environment that isn't up-to-snuff.  In the Linux world (Ubuntu and equivalents, really) you can code your scripts to perform an apt-get which will get the required software if it isn't present.  Under the covers these things are using curl and wget to download and install what is needed.  

We have no concept of this natively in Windows but that doesn't make it right.  gitFetchAll.ps1 is a Posh script that I will use for the remainder of this blog post.  I wrote a function called loadPoshGit that will load the module regardless of whether it is even currently installed.  The code to do that is very simple.  I really like using this pattern in all of my code where I have a dependency on some small utility that may not be available.  This helps out an Ops Guy that may not know or remember where that certain utility can be found.  This pattern will work for any piece of code that is downloadable from your machine.  

Automating git on Windows

Now that we can guarantee we have posh-git installed and loaded into our profile we can run some git commands.  gitFetchAll.ps1 is the script I wrote that takes a folder structure of git repositories and remotely fetches and merges any new changes.  Here isthe guts of the script:  

$RootFolder is declared by you.  We find every $subfolder in that $RootFolder and traverse it, calling git pull (fetch and merge) in every folder.  

That is ridiculously easy.

Let's see what this looks like:  

  • I first perform a cd to get to my script location
  • Then I launch powershell and call gitFetchAll.ps1 in a single command
  • Ignore the WARNING...that's an artifact of some other testing I'm doing with git (my ssh is currently broken on my laptop)
  • You can see that I then cd into each folder and call git pull.
    • ...which gets me the latest code on the remote repo if it can
    • ...or simply notifies me that the code is "Already up-to-date"


One last pattern:  pushd and popd

One last pattern I like to do is on Line 62 above.  The popd command.  Whenever I have a Posh script that does a "cd" I ensure that I first capture the user's pwd (print working directory) using pushd.  I then ensure that I exit the script in the same folder, using popd.  It's obnoxious to find scripts that don't do that and it makes automation routines difficult when a script has "side-effects" such as changing your working folder.  


I use this script every morning to get the latest from my remote repos.  It illustrates how to automate git on Windows using Powershell which is much less kludgey than cygwin.  The script is lacking good error-handling but I don't require it for my needs and I just wanted to demonstrate some useful git automation routines.  I also outlined two other patterns I like to use in my Posh scripts...auto-installing helper utilities if they are mising and using pushd and popd to ensure your scripts have no side-effects.  

You have just read git and Powershell Integration on davewentzel.com. If you found this useful please feel free to subscribe to the RSS feed.  

PoSH script to back up VMs on Win8 Hyper-V

I received a Win8 laptop a few weeks ago and one of nifty new features is the ability to do native Hyper-V VMs, assuming your hardware supports it.  I have been a big fan of using VMs to do just about all of my development, especially when I have to deal with projects using multiple versions of Visual Studio.  It's so much easier to only put one version of VS on your laptop and then the other versions on VMs.  I also do a lot of open source, Linux-based development (almost every NoSQL solution runs on Linux).  It's much easier to spin up a Bitnami stack on a new Linux VM to run Ruby or GitLab rather than trying to get everything to cooperate on a single Ubuntu installation.  

I formerly used a bunch of old, junk hardware to spin up these stacks.  There's only so many VMs you can spin up in MS VirtualServer 2005.  Things are so much better with Hyper-V on Windows 8.  But it's still a bit of a PITA to back up a VM.  This is a bit better in 8.1 where you can backup a running VM without a snapshot or a saved state.  In Win8 you must minimally Save State, Export the VM, then Resume State.  I tried to find a PoSH script that does this on google but couldn't find one.  

So I wrote my own that I'm sharing in git.  At the right is the script header for reference. You simply provide a path to store your backup.  The script will find all VMs on your host and will, in turn, save, export, and resume each VM.  Please note that this is not a production-quality script.  It lacks good error handling and does cause a few minutes of downtime while the export is occurring.  But it does work flawlessly as a development backup solution.  


Free Space on Mount Points

It seems overly difficult to write a quick script to check the free space on a mount point.  It turns out there is a simple way to do this using PowerShell.  

get-wmiobject win32_volume -filter "FileSystem='NTFS'" | select name, capacity, freespace


The SQL Server 2008 installer bombs out if a "pending reboot required" is detected.  This is due to a registry value called PendingFileRenameOperations that contains a list of files that need to be renamed/moved/deleted but can't be because they are in use.  Generally this is no big deal but our software is meant to install on customer laptops, which means we have absolutely no idea what garbage they have installed. 

Subscribe to RSS - PowerShell