Over the past couple of weeks I’ve had several people ask me about my dev environment for working with Git on Windows so I decided to write it up here for me to point people to. Of course the first thing that you want is Visual Studio 2013 with the built in Git tooling. While I’m obviously very biased in terms of the Visual Studio tools I’m actually more familiar with the command line workflow – especially coming from the Mac. However the team specifically designed the Visual Studio tools to work well with the command line and compliment them – I find myself swapping more and more between the command line and the UI depending on what’s quickest for me. I NEVER use the command line for merging any more, but I still use if for dealing with multiple remotes (very common in OSS workflows) squashing and rebasing my commits etc. There are some things I actually find myself using Visual Studio for that I never thought I would. For example I quite often find myself swapping my email address around when I’m doing commits for work or if I’m working on a demo or a side project and I’ve noticed I’ve been using the Git settings panel in Team Explorer more and more rather than going to “git config” which surprised me.

So, how do I set up my command line Git experience?

First of all you have to install Git for Windows of course.  I always use the .exe installer from here (ignore the –preview moniker, they are good – at the time of writing the latest is Git-1.8.5.2-preview20131230.exe). Now one of the first mistakes I see people do is go for the default options in the installer which results is people using Git Bash. If you love yourself don’t do that, but make sure Git is added to your path. On the screens that I need to make decisions on, I always follow this path.

For component selection, I generally go for the defaults. I don’t use the shell extensions personally but they don’t hurt.

image

This is the important one being the change to make sure Git is added to your Path. This makes sure that you can go to the command shell or PowerShell and run Git. The Git Bash shell is evil IMHO, I never find myself using it despite using Bash all the time when I’m on *nix.

image

Then I go with the default of setting the CRLF behaviour to normalize as Unix style endings in the commits.  Basically this makes sure a commit generated on Windows is the same as one done on the Mac or on Linux but also that you can still use notepad if you check out a file that was edited in Vim on Linux.

image

 

At this point you now have Git installed. Congratulations!  However, you can do better than that…

Enter PoshGit

The next thing I install is PoshGit. I swear, PoshGit is the main reason to use the PowerShell console (that and also the fact it doesn’t shout at you when you accidentally type “ls” instead of “dir”) Installation of PoshGit can be a bit quirky but Keith’s instructions are pretty good. Basically, after he’s helped you make sure your PowerShell environment is set up correctly, you clone the repo (git clone https://github.com/dahlbyk/posh-git.git), cd into it and then run the install script.

I always use Git over HTTPS rather than SSH so I often don’t have Putty installed with Paegent to handle my keys. Therefore I tend to just comment out the Start-SshAgent -Quiet line in \posh-git\profile.example.ps1. If you are seeing the error “WARNING: Could not find ssh-agent” when you start PowerShell and you don’t need SSH then just open up profile.example.ps1 in notepad, scroll down to the end of the file and make sure it looks like this:

   ...

Enable-GitColors

Pop-Location

# Start-SshAgent -Quiet

 

Remembering Passwords

Next up I install Andrew Nurse’s credential helper, git-credential-winstore. If you are talking to a Git server that requires a username and password, rather than having to type your credentials all the time this nifty little helper will actually store them securely in the Windows Credential Manager.  Note that when installing you’ll see an error if you’ve gone for the middle option when setting your path in Git for Windows because Git.exe isn’t on your path (Git.cmd is).  Therefore you are going to want to:

  1. Download it from CodePlex and save it to your disk
  2. In a command / powershell window, cd into your Downloads folder
  3. Install the credential helper by typing:

git-credential-winstore.exe -I "C:\Program Files (x86)\Git\bin\git.exe"

Combined with with web interface in TFS, Visual Studio 2013 and Eclipse with egit, that’s all I need personally. However if you want a graphical view of your repository then a lot of people use gitk which is installed with Git for Windows (just type “gitk” inside your repo in the command shell / powershell windows).  You can also type “git gui” for the git-gui tools.  Other popular graphical tools you might want to install are GitHub’s free app GitHub for Windows and Atlassian’s free app SourceTree.  GitHub for Windows is very pretty and great for managing your GitHub based repos. Atlassian’s SourceTree is very highly regarded as stand-alone UI for working with Git repos on Windows.

If you want to work with your local Git repositories in some .NET code then LibGit2Sharp is your friend.  It’s the open source library used by the Visual Studio Tools for Git and gives you a very idiomatic way to talk to Git from C# or VB.NET.  I thought it would be worth a quick tutorial post showing how easy it is to get started by querying a repository helping us learn a bit about the library but also learn more about Git itself. As LibGit2Sharp is open source in this example I’m going to point to cloned copy of the repository I have locally already by using the Git tooling in Visual Studio or by typing git clone https://github.com/libgit2/libgit2sharp.git. However you can obviously point to any Git repository you already have locally.

To begin, create a new console project in Visual Studio. We need to add a reference to the Lib2Sharp library and the quickest way to do that is to open the NuGet package manager by right-clicking on your project in Solution Explorer and select Manage NuGet Packages…  Search online for “LibGit2Sharp” and Install.

NPM to install LibGit2Sharp

Then accessing an existing repo is trivial, simply use the LibGit2Sharp.Repository class. A handy way to get a particular commit is by its hash if you know it.

      public static void Main(string[] args)
      {
         
using (var repo = new Repository(@"D:\source\LibGit2Sharp"
))
          {
             
Commit commit = repo.Lookup<Commit>("73b48894238c3e9c37f9f3a696bbd4bffcf45ce5"
);
             
Console.WriteLine("Author: {0}"
, commit.Author.Name);
             
Console.WriteLine("Message: {0}"
, commit.MessageShort);
          }
      }

But what if we just want the commit that’s the latest of the current branch, in Git-speak we want the “Tip” of “Head”. LibGit2Sharp gives you an easy way to get to the Head through the repository object. So we can do the following:

    public static void Main(string[] args)
      {
         
using (var repo = new Repository(@"D:\source\LibGit2Sharp"
))
          {
             
Commit
commit = repo.Head.Tip;
             
Console.WriteLine("Author: {0}"
, commit.Author.Name);
             
Console.WriteLine("Message: {0}"
, commit.MessageShort);
          }
      }

A point in time in the repository is represented by a Commit. Each Commit points to a Tree which you can think of as a directory/folder. A Tree can contain a Blob (i.e. the contents of a file) or another Tree (i.e. a sub-folder).

So if you want to list the contents at the root of the repository then you can do

        foreach(TreeEntry treeEntry in commit.Tree)
        {
           
Console.WriteLine("Path:{0} - Type:{1}"
, treeEntry.Path, treeEntry.TargetType);
        }

That will give you something like the following when against the LibGit2Sharp repository

Path:.gitattributes - Type:Blob
Path:.gitignore - Type:Blob
Path:.gitmodules - Type:Blob
Path:.mailmap - Type:Blob
Path:.travis.yml - Type:Blob
Path:CHANGES.md - Type:Blob
Path:CI-build.msbuild - Type:Blob
Path:LICENSE.md - Type:Blob
Path:Lib - Type:Tree
Path:LibGit2Sharp.Tests - Type:Tree
Path:LibGit2Sharp.sln - Type:Blob
Path:LibGit2Sharp - Type:Tree
Path:README.md - Type:Blob
Path:ResharperSettings.xml - Type:Blob
Path:UpdateLibgit2ToSha.ps1 - Type:Blob
Path:build.libgit2sharp.cmd - Type:Blob
Path:build.libgit2sharp.sh - Type:Blob
Path:build.libgit2sharp.x64.cmd - Type:Blob
Path:libgit2 - Type:GitLink
Path:nuget.package - Type:Tree
Path:square-logo.png - Type:Blob

To see which files changed in a particular commit.  To do that we need to find the diff between the commit and it’s parent. For now let’s just assume that we have a single parent (i.e. we’re not a merge commit). Therefore we can do this

        Tree commitTree = repo.Head.Tip.Tree;
       
Tree
parentCommitTree = repo.Head.Tip.Parents.Single().Tree;

       
TreeChanges
changes = repo.Diff.Compare(parentCommitTree, commitTree);

       
Console.WriteLine("{0} files changed.",changes.Count());

And finally to iterate over the changes to show what files changed in that commit

        foreach(TreeEntryChanges treeEntryChanges in changes)
        {
           
Console.WriteLine("Path:{0} +{1} -{2} "
,
                    treeEntryChanges.Path,
                    treeEntryChanges.LinesAdded,
                    treeEntryChanges.LinesDeleted
                );
        }

That then gives the following output

Author: nulltoken
Message: Release LibGit2Sharp v0.11
3 files changed.
Path:LibGit2Sharp.Tests\DiffTreeToTreeFixture.cs +35 -11
Path:LibGit2Sharp.Tests\LibGit2Sharp.Tests.csproj +1 -0
Path:LibGit2Sharp.Tests\TestHelpers\OdbHelper.cs +17 -0

This post obviously just scratches at the surface of what is possible with LibGit2Sharp. We’re starting the process of trying to flesh out the documentation for the project from the current starting position of none, but it the meantime if you want to see some more examples of using LibGit2Sharp then take a look at the Unit Tests.

Source Code: Commit1.cs

Eclipse Juno Themes on Windows

I’ve been running Eclipse Juno regularly since the M5 milestone.  One of the things I’ve really noticed is that the default theme for Eclipse Juno on Mac OS X blends in better with other Cocoa applications than Juno looks on my Windows machines. Today I just realised that this is because Eclipse is picking up the Eclipse “Windows XP Blue” theme by default. Below is a picture of Juno RC3 with a Windows Explorer window over it for comparison.

Eclipse Juno RC3 on Windows XP Release Preview

To change the theme, go to Window, Preferences, General, Appearance and select Windows 7.  This looks a lot better on my Windows 8 Release Preview machine as shown below.

Eclipse Juno RC3 on Windows XP Release Preview with Windows 7 theme

Now, one of the great things about e4 is that it is skinnable using CSS.  I thought I’d knock up a quick stylesheet to get rid of the gradient in the toolbar and tidy up a few other little things.  It’s also really easy to define a theme as part of the plugin.xml and only have it apply to people running Windows 8 – simply add the following (note the condition on OS version of 6.2):

<extension
point="org.eclipse.e4.ui.css.swt.theme">
   <theme
         basestylesheeturi="css/e4_default_win8.css"
         id="org.eclipse.e4.ui.css.theme.e4_default"
         label="Windows 8 Desktop"
         os="win32"
         os_version="6.2"
>
   </theme>
</extension>

This is what my Windows 8 theme for Juno currently looks like against explorer:

Eclipse Juno RC3 on Windows XP Release Preview with custom theme

Needs a bit of playing with (for example, I’ve noticed that swapping themes in Eclipse works a lot better if you explicitly override things like the background images that have been used previously in themes in that Eclipse session rather than just leaving them not set).  What do you think?  If you are interested the CSS is below but it’s just a subtly changed version of the default win7 theme.

@import url('e4_basestyle.css');
.MTrimmedWindow {
    background-color: #EFF6FE;
}

.MPartStack {
    font-size: 9;
    font-family: 'Segoe UI';
    swt-simple: true;
    swt-mru-visible: false;
}

.MTrimBar {
    background-color: #EFF6FE;
}

.MToolControl.TrimStack {
    frame-image:  url("./win7TSFrame.png");
    handle-image:  url("./win7Handle.png");
}

.MPartStack.active {
    swt-unselected-tabs-color: #F3F9FF #D0DFEE #CEDDED #CEDDED #D2E1F0 #D2E1F0 #FFFFFF 20% 45% 60% 70% 100% 100%;
    swt-outer-keyline-color: #B6BCCC;
}

#PerspectiveSwitcher  {
    background-color: #E1E6F6 #EFF6FE 100%;
}

#org-eclipse-ui-editorss {
   swt-tab-renderer: url('bundleclass://org.eclipse.e4.ui.workbench.renderers.swt/org.eclipse.e4.ui.workbench.renderers.swt.CTabRendering');
   swt-unselected-tabs-color: #F0F0F0 #F0F0F0 #F0F0F0 100% 100%;
   swt-outer-keyline-color: #B4B4B4;
   swt-inner-keyline-color: #F0F0F0;
   swt-tab-outline: #F0F0F0;
   color: #F0F0F0;
   swt-tab-height: 8px;
   padding: 0px 5px 7px;
}

CTabFolder.MArea .MPartStack, CTabFolder.MArea .MPartStack.active {
   swt-shadow-visible: false;
}

CTabFolder Canvas {
  background-color: #F8F8F8;
}


Anyway, lesson from this is to at least change the theme in Juno on Windows 8 from Windows XP Blue to the Windows 7. The jury is still out on my customized stylesheet above – I’m sure someone with some actual design skills could do better.

TFS from the Raspberry Pi

I just got delivery of my shiny new Raspberry Pi.  With-in a few minutes I had it all booted and running a stock Debian “squeeze” image, almost too easy and the performance of the diminutive Raspberry Pi was great. Previously my experiences with Embedded Linux has mostly been when running on hacked router firmwares so running on a chip as powerful as the ARM v11 Broadcoam chip in the Raspberry Pi is a real pleasure.  As getting it up and running was so easy, what should be my first project on my latest (and least expensive ever) computer?  I thought I’d see what it took to talk to TFS from the device :-)

Accessing TFS from a Raspberry Pi

First things first, I had to get Java installed.  It sounds like Oracle are working on a version of Java with a proper Hotspot JVM – but I just went with a vanilla OpenJDK build for the device that lacks important features like a JIT etc.  It’s all fully functional, just the performance isn’t great but sticking to the TFS cross-platform command line client (tf) in Team Explorer Everywhere, performance is usable and will only get better as better JVM’s come available for the Raspberry Pi.

To install a JRE you would just do the usual:

sudo apt-get install openjdk-6-jre

However, I needed to do some building on the Raspberry Pi and needed a full JDK so I went with:

sudo apt-get install openjdk-6-jdk

And then set my JAVA_HOME by adding the following to my profile

export JAVA_HOME=/usr/lib/jvm/java-6-openjdk/

Now, I like to say that Team Explorer Everywhere is 99.99% Java.  All the code to talk to the TFS webservices is all Java based, however there is a small but very important set of native code that we also ship with our Cross-platform command line client, the Eclipse plug-in and the TFS SDK for Java.  The native code does things that are hard to do otherwise such as see how many columns are available in the current console session, use Key Ring of Keychain for secure credential storage, interface with the platforms native Kerberos libraries if present to allow for single sign-on with TFS etc.  My next step to get tf working on the Raspberry Pi was to compile our native code for the armv6l based chipset.  As mentioned this native code includes Kerberos support so I first had to add the Kerberos libraries (sudo apt-get install libkrb5-dev - note you wouldn’t have to do this if you didn’t need Kerberos support as we also support NTLMv2 out the box without requiring any additional dependencies)

I ran the native build process, and amazingly all the unit tests passed!  I then checked the Linux/Arm natives back into TFS, waiting for the CI build to finish and then downloaded a new TFS-CLC.zip from the build server.  Unzipped the standard CLC into my users ~/Bin directory and it just worked!

I can now happily talk to my local TFS server from my $25 Raspberry Pi.  With local workspaces and transparent execute bit support in TFS 2012 it’s a really good experience. I just use vim to edit files, do a quick “tf status” to see what's changed and then a “tf checkin” to add the files to source control.

I’ve actually added the Linux on Arm natives into the main build of TEE so they might appear in the RTM version of Team Explorer Everywhere if I don’t find any major bugs.  It definitely wouldn’t be classed as a supported platform or anything, but it certainly “works on my machine”.  Possibly more useful is that if the Arm natives also ship in our TFS SDK for Java it would mean any Java applications coded on the Raspberry Pi in the future would have full access to the same TFS API that we use to create the command line client and the Eclipse plug-ins.

Picture of the Raspberry Pi running TEE against my ID badge for scaleUpdate: I was getting some questions on Twitter, so just to explain how small this device is here is a picture of it against my Microsoft ID Card (which is credit card sized).  The Raspberry PI is almost exactly the same size.  The ARM CPU on it is about the size of a thumbnail – much smaller than the HDMI and Ethernet connection it is attached to.  Really nice piece of kit for $25 if you can get hold of one.

All this was anti-climatically easy. I’m going to have to figure out what to do as my next Raspberry Pi project.  Now that I have an API I can use for TFS, I’m thinking about doing a Wallboard display application to display stats from my TFS server (such as latest build status, latest check-ins and work item assignments etc) from the device onto a cheap HDMI TV set in my office – but if anyone has any other ideas let me know.

If you are looking to extend Team Foundation Build using workflow activities, then the first thing you should do it take a look at the latest stable release of the Community TFS Build Extensions over on CodePlex.  This is a collection of around 100 activities that can provide many commonly requested functions incluing running CodeMetrics and NUnit tests, creating a Zip archive, wrapping RoboCopy for deployment, updating AssemblyInfo files, running StyleCop, merging assemblies with ILMerge etc etc.  Basically most of the building blocks for major common customization already done for you.  Also – as it’s an open source project ran by the MVP community you have access to a bunch of great code that shows you how to create your own activity should you want to do something that has yet to be done (don’t forget to contribute it back if you can)

Great job to the team of folks contributingg to the community build extensions (many of which I am proud to call my friends) – I’m looking forward to seeing the project go from strength to strength now that they have their first stable release out the door.

As you have probably heard by now, Eclipse 3.7 shipped today.  Congratulations to everyone involved.  From a personal point of view I’m secretly pleased to see that one of my own bug reports manage to sneak it’s way in to this release as well which I think means I have managed to do my bit and contribute a little something to every Eclipse since 3.4

We’ve been tracking the Indigo release internally through the latter milestone builds and so far we’ve yet to discover any issues when using Eclipse 3.7 with Team Explorer Everywhere 2010 SP1 (as many of the team do every day).

Eclipse 3.7 with Team Explorer Everywhere 2010 SP1

Let me know if you think you do find something but as we don’t use any internal Eclipse API’s, we stick to the standard Eclipse contributions and install via the standard update site model - Eclipse 3.7 is looking very good with TEE 2010 SP1.

I’ll be showing off Team Explorer Everywhere 2010 SP1 in Indigo at the following events over the next few days:

This weekend I thought I would get round to a project that I’ve been meaning to do for a long time – a new website for the Radio TFS podcast that I do with Mickey and Paul.  I haven’t had the chance to play with WebMatrix before so thought that I would give it a try when building the new Radio TFS site.  I’m also behind in my learning's around ASP.NET MVC, WebDeploy and IIS 7 so it’s going to be a good weekend! 

One thing that I wanted to do was make sure that all the old episode links redirect to the new locations.  To do this I’m building a HttpHandler that listens for all the requests ending in *.aspx (which is what the episode links did) and then look up that link in the database to redirect them to the new link.  However it took me a while to figure out how to create a HttpHandler in Webmatrix.  As with everything – once you know the answer it is easy but as it took me a while to figure out I’m documenting it here in case others try searching for the answer with the same keywords I was using.

The first step is to create your HttpHandler class.  In the App_Code directory in your WebMatrix site create a new C# file (mine is called LegacyUrlHandler.cs).  A very simple HttpHandler is below.

using System;
using System.Collections.Generic;
using System.Web;

namespace RadioTFS
{
    public class LegacyURLHttpHandler : IHttpHandler
    {
        public bool IsReusable
        {
            // The same instance of this class can be re-used so we return true.
            get {
                return true;
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            HttpResponse response = context.Response;
            response.Write("<html><body><h1>Hello World!</h1></body></html>");
        }
    }
}

You then have to register this HttpHandler in the web.config.  Assuming this is being deployed to IIS7 you register it as follows:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        .....
        <handlers>
            <add name="LegacyUrlHandler" verb="*"
                path="*.aspx"
                type="RadioTFS.LegacyURLHttpHandler"
                resourceType="Unspecified" />
        </handlers> 
    </system.webServer>
    ....
</configuration>

Hope that helps you.  I’ll probably be blogging again over the weekend as I discover more – and I’ll definitely let you know when the new site is live.

Archives

Recent Comments

  • Klas: Do you know how to grant access to a single read more
  • Mike Parks: If you have Visual Studio 2010 w/TFS 2010, check out read more
  • Chris: Occasionally, GMail loses its marbles and offers a Basic HTML read more
  • Martin Woodward: Ryan - yes, we still provide a complimentary CodePlex license. read more
  • ryan: will 'codeplex only' licenses still exist for TEE like they read more
  • Sarah: @Ethan & @bString ... and maybe all those asking the read more
  • mohan: I am not able to run build using the read more
  • Frank: Cool! Thanks for this tip! Finally my over 2000 unread read more
  • mahesh: HELLO SIR, I'm new at .net I want to create read more
  • stuart: saved my morning! google notifier was displaying thousands of unread read more
Creative Commons License
This blog is licensed under a Creative Commons License.