<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://www.lostechies.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>James Gregory's Blog</title><link>http://www.lostechies.com/blogs/jagregory/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Git E-VAN recording</title><link>http://www.lostechies.com/blogs/jagregory/archive/2010/02/17/git-e-van-recording.aspx</link><pubDate>Wed, 17 Feb 2010 04:44:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:70107</guid><dc:creator>James Gregory</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=70107</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2010/02/17/git-e-van-recording.aspx#comments</comments><description>&lt;p&gt;Last monday (8th of Feb) I did an &lt;a href="http://jagregory.com/writings/git-e-van/"&gt;E-VAN on Git&lt;/a&gt;; an introductory talk on Git and DVCS, covering pretty much everything you need to know for day-to-day Git life. I think it went down well, certainly didn't &lt;em&gt;hear&lt;/em&gt; anyone complaining.&lt;/p&gt;

&lt;p&gt;The talk was recorded, so if you haven't already seen it then you can do so at your own leisure.&lt;/p&gt;

&lt;p&gt;The video is up on the &lt;a href="http://vimeo.com/user1286822"&gt;E-VAN's Vimeo account&lt;/a&gt;, specifically &lt;a href="http://vimeo.com/9324683" title="Git E-VAN recording"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=9324683&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00ADEF&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=9324683&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00ADEF&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="600" height="450"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Git+E-VAN+recording&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2010%2f02%2f17%2fgit-e-van-recording.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2010%2f02%2f17%2fgit-e-van-recording.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=70107" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/git/default.aspx">git</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/speaking/default.aspx">speaking</category></item><item><title>Git: Remotes, contributions, and the letter N</title><link>http://www.lostechies.com/blogs/jagregory/archive/2010/02/12/git-remotes-contributions-and-the-letter-n.aspx</link><pubDate>Fri, 12 Feb 2010 02:23:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:66614</guid><dc:creator>James Gregory</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=66614</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2010/02/12/git-remotes-contributions-and-the-letter-n.aspx#comments</comments><description>Here's a few ways to think about Git and it's distributed nature.

&lt;ul&gt;
&lt;li&gt;You deal with multiples of repositories, not a single central repository&lt;/li&gt;
&lt;li&gt;Updates come from a remote repository, and changes are pushed to a remote; none of these repositories have to be the same&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Origin&lt;/em&gt; is the canonical name for the repository you cloned from&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Upstream&lt;/em&gt; is the canonical name for the original project repository you forked from&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;General pushing and pulling&lt;/h2&gt;

&lt;p style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitRemotes/remote_2D00_1.png" /&gt;&lt;/p&gt;

Pushing your changes to a remote: &lt;code&gt;git push remote_name&lt;/code&gt;

&lt;p style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitRemotes/remote_2D00_2.png" /&gt;&lt;/p&gt;

Pulling changes from a remote: &lt;code&gt;git pull remote_name&lt;/code&gt;

Or if you want to rebase:
&lt;pre&gt;git fetch remote_name
git rebase remote_name/branch&lt;/pre&gt;

&lt;blockquote&gt;You can change your &lt;code&gt;branch.autosetuprebase&lt;/code&gt; to &lt;code&gt;always&lt;/code&gt;, to make this the default &lt;code&gt;git pull&lt;/code&gt; behaviour.&lt;/blockquote&gt;

That's all there is to moving commits around in Git repositories. Any other operations you perform are all combinations of the above.

&lt;h2&gt;Github &amp;mdash; personal repositories&lt;/h2&gt;

When you're dealing directly with Github, on a personal project or as the project owner, your repositories will look like this:

&lt;p style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitRemotes/remote_2D00_3.png" /&gt;&lt;/p&gt;

To push and pull changes between your local and your github repositories, just issue the push and pull commands with the origin remote:

&lt;pre&gt;git push origin
git pull origin&lt;/pre&gt;

You can set the defaults for these commands too, so the origin isn't even necessary in a lot of cases.

&lt;h2&gt;Github &amp;mdash; receiving contributions&lt;/h2&gt;

As a project owner, you'll sometimes have to deal with contributions from other people. Each contributor will have their own github repository, and they'll issue you with a pull request.

&lt;p style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitRemotes/remote_2D00_4.png" /&gt;&lt;/p&gt;

There's no direct link to push between these two repositories; they're unmanned. To manage changes from contributors, you need to involve your local repository.

You can think of this as taking the shape of a V.

&lt;p style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitRemotes/remote_2D00_5.png" /&gt;&lt;/p&gt;

You need to register their github repository as a remote on your local, pull in their changes, merge them, and push them up to your github. This can be done as follows:

&lt;pre&gt;git remote add contributor contributor_repository.git
git pull contributor branch
git push&lt;/pre&gt;


&lt;h2&gt;Github &amp;mdash; providing contributions&lt;/h2&gt;

Do exactly as you would your own personal project. Local changes, pushed up to your github fork; then issue a pull request. That's all there is to it.


&lt;h2&gt;Github &amp;mdash; the big picture&lt;/h2&gt;

Here's how to imagine the whole process, think of it as an N shape.

&lt;p style="text-align:center;"&gt;&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitRemotes/remote_2D00_6.png" /&gt;&lt;/p&gt;
    
On the left is the contributor, and the right is the project. Flow goes from bottom left, along the lines to the top right.

&lt;ol&gt;
&lt;li&gt;Contributor makes a commit in their local repository&lt;/li&gt;
&lt;li&gt;Contributor pushes that commit to their github&lt;/li&gt;
&lt;li&gt;Contributor issues a pull request to the project&lt;/il&gt;
&lt;li&gt;Project lead pulls the contributor's change into their local repository&lt;/li&gt;
&lt;li&gt;Project lead pushes the change up to the project github&lt;/li&gt;
&lt;/ol&gt;

That's as complicated as it gets.&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Git%3a+Remotes%2c+contributions%2c+and+the+letter+N&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2010%2f02%2f12%2fgit-remotes-contributions-and-the-letter-n.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2010%2f02%2f12%2fgit-remotes-contributions-and-the-letter-n.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=66614" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/git/default.aspx">git</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/github/default.aspx">github</category></item><item><title>Behaviours in MSpec</title><link>http://www.lostechies.com/blogs/jagregory/archive/2010/01/18/behaviours-in-mspec.aspx</link><pubDate>Mon, 18 Jan 2010 12:42:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:50759</guid><dc:creator>James Gregory</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=50759</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2010/01/18/behaviours-in-mspec.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://github.com/machine/machine.specifications"&gt;MSpec&lt;/a&gt; is awesome, I think it's praised by myself and others enough for that particular point to not need any expansion; however, there is a particular feature I would like to highlight that hasn't really got a lot of press: behaviours.&lt;/p&gt;

&lt;p&gt;Behaviours define reusable specs that encapsulate a particular set of, you guessed it, behaviours; you're then able to include these specs in any context that exhibits a particular behaviour.&lt;/p&gt;

&lt;p&gt;Lets go with the cliche'd Vehicle example. Given an &lt;code&gt;IVehicle&lt;/code&gt; interface, with &lt;code&gt;Car&lt;/code&gt; and &lt;code&gt;Motorbike&lt;/code&gt; implementations; these all expose a &lt;code&gt;StartEngine&lt;/code&gt; method and some properties reflecting the state of the vehicle. We'll start the engine and verify that it is actually started, whether it's got anything on the rev counter, and whether it's killing our planet in the process (zing!).&lt;/p&gt;

&lt;pre name="code" class="c-sharp"&gt;
public interface IVehicle
{
  void StartEngine();
  bool IsEngineRunning { get; }
  bool IsPolluting { get; }
  int RevCount { get; }
}

public class Car : IVehicle
{
  public bool IsEngineRunning { get; private set; }
  
  public void StartEngine()
  {
    // use your imagination...
  }
}

public class Motorbike : IVehicle
{
  public bool IsEngineRunning { get; private set; }

  public void StartEngine()
  {
    // use your imagination...
  }
}
&lt;/pre&gt;

&lt;p&gt;Those are our classes, if rather contrived, but they'll do. Now what we need to do is write some specs for them.&lt;/p&gt;

&lt;pre name="code" class="c-sharp"&gt;
public class when_a_car_is_started
{
  Establish context = () =&gt;
    vehicle = new Car();
  
  Because of = () =&gt;
    vehicle.StartEngine();
  
  It should_have_a_running_engine = () =&gt;
    vehicle.IsEngineRunning.ShouldBeTrue();
  
  It should_be_polluting_the_atmosphere = () =&gt;
    vehicle.IsPolluting.ShouldBeTrue();
  
  It should_be_idling = () =&gt;
    vehicle.RevCount.ShouldBeBetween(0, 1000);
  
  static Car vehicle;
}

public class when_a_motorbike_is_started
{
  Establish context = () =&gt;
    vehicle = new Motorbike();
  
  Because of = () =&gt;
    vehicle.StartEngine();
  
  It should_have_a_running_engine = () =&gt;
    vehicle.IsEngineRunning.ShouldBeTrue();

  It should_have_a_running_engine = () =&gt;
    vehicle.IsEngineRunning.ShouldBeTrue();

  It should_be_polluting_the_atmosphere = () =&gt;
    vehicle.IsPolluting.ShouldBeTrue();

  It should_be_idling = () =&gt;
    vehicle.RevCount.ShouldBeBetween(0, 1000);
  
  static Motorbike vehicle;
}
&lt;/pre&gt;

&lt;p&gt;Those are our specs, there's not much in there but already you can see that we've got duplication. Our two contexts contain identical specs, they're the same in what they're verifying, the only difference is the vehicle instance. This is where behaviours can come in handy.&lt;/p&gt;

&lt;p&gt;With behaviours we can extract the specs and make them reusable. Lets do that.&lt;/p&gt;

&lt;p&gt;Create a class for your behaviour and adorn it with the &lt;code&gt;Behaviors&lt;/code&gt; attribute &amp;mdash; this ensures MSpec recognises your class as a behaviour definition and not just any old class &amp;mdash; then move your specs into it.&lt;/p&gt;

&lt;pre name="code" class="c-sharp"&gt;
[Behaviors]
public class VehicleThatHasBeenStartedBehaviors
{
  protected static IVehicle vehicle;
  
  It should_have_a_running_engine = () =&gt;
    vehicle.IsEngineRunning.ShouldBeTrue();

  It should_have_a_running_engine = () =&gt;
    vehicle.IsEngineRunning.ShouldBeTrue();

  It should_be_polluting_the_atmosphere = () =&gt;
    vehicle.IsPolluting.ShouldBeTrue();

  It should_be_idling = () =&gt;
    vehicle.RevCount.ShouldBeBetween(0, 1000);
}
&lt;/pre&gt;

&lt;p&gt;We've now got our specs in the behaviour, and have defined a field for the vehicle instance itself (it won't compile otherwise). This is our behaviour complete, it defines a set of specifications that verify that a particular behaviour.&lt;/p&gt;

&lt;p&gt;Lets hook that behaviour into our contexts from before:&lt;/p&gt;

&lt;pre name="code" class="c-sharp"&gt;
public class when_a_car_is_started
{
  Establish context = () =&gt;
    vehicle = new Car();
  
  Because of = () =&gt;
    vehicle.StartEngine();
  
  Behaves_like&amp;lt;VehicleThatHasBeenStartedBehaviors&amp;gt; a_started_vehicle;
  
  protected static Car vehicle;
}

public class when_a_motorbike_is_started
{
  Establish context = () =&gt;
    vehicle = new Motorbike();
  
  Because of = () =&gt;
    vehicle.StartEngine();
  
  Behaves_like&amp;lt;VehicleThatHasBeenStartedBehaviors&amp;gt; a_started_vehicle;
  
  protected static Motorbike vehicle;
}
&lt;/pre&gt;

&lt;p&gt;We've now put to use the &lt;code&gt;Behaves_like&lt;/code&gt; feature, which references our behaviour class and imports the specs into the current context. Now when you run your specs, the specs from our behaviour are imported and run in each context. We don't need to assign anything to that field, just defining it is enough; the name you choose for the field is what's used by MSpec as the description for what your class is behaving like. In our case this is translated roughly to &lt;em&gt;"when a motorbike is started it behaves like a started vehicle"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There are a couple of things you need to be aware of to get this to work: your fields must be &lt;code&gt;protected&lt;/code&gt;, both in the behaviour and the contexts; and the fields must have identical names. If you don't get these two correct your behaviour won't be hooked up properly. It's also good to know that the fields &lt;strong&gt;do not&lt;/strong&gt; need to have the same type, as long as the value from your context is assignable to the field in the behaviour then you're good; this is key to defining reusable specs for classes that share a sub-set of functionality.&lt;/p&gt;

&lt;p&gt;In short, behaviours are an excellent way of creating reusable specs for shared functionality, without the need to create complex inheritance structures. It's not a feature you should use lightly, as it can greatly reduce the readability of your specs, but it is a good feature if you've got a budding spec explosion nightmare on your hands.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Behaviours+in+MSpec&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2010%2f01%2f18%2fbehaviours-in-mspec.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2010%2f01%2f18%2fbehaviours-in-mspec.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=50759" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/bdd/default.aspx">bdd</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/mspec/default.aspx">mspec</category></item><item><title>Git guts: Merging and rebasing</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/11/27/git-guts-merging-and-rebasing.aspx</link><pubDate>Fri, 27 Nov 2009 05:54:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:36170</guid><dc:creator>James Gregory</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=36170</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/11/27/git-guts-merging-and-rebasing.aspx#comments</comments><description>&lt;p&gt;Here we go again, explaining the internals of Git with the intention of helping you understand what you're doing day-to-day. Last time I covered &lt;a href="http://www.lostechies.com/blogs/jagregory/archive/2009/11/25/git-s-guts-branches-head-and-fast-forwards.aspx"&gt;branches, HEAD, and fast-forwarding&lt;/a&gt;. Today we'll dive into the guts of merging and rebasing.&lt;/p&gt;

&lt;h3&gt;Merging branches&lt;/h3&gt;

&lt;p&gt;You've probably merged before. You do it when you want the changes from one branch in another. The principal is the same in Git as it is most other source control systems, but the implementation differs.&lt;/p&gt;

&lt;p&gt;Given the following commit structure, consisting of two branches created from the same commit, each with two commits after the branching occurred.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure1.png" /&gt;

&lt;p&gt;When these two branches are merged together, this is the structure that results:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure2.png" /&gt;

&lt;p&gt;The top-most commit, the red one, is a new commit made by the merge; the merge commit is what reminds Git that a merge occurred next time it's showing the history. This commit is special, as it contains multiple parent's in it's meta-data; these multiple parent's allow Git to follow the two trees of commits that constituted the branches that were merged.&lt;/p&gt;

&lt;p&gt;One difference in how Git handles merges compared to many other SCMs is that it preserves the commits that were made in both branches. In other systems merges are often represented as a single commit containing the squashed contents of all the commits that were made in the branch being merged in. Git doesn't do this (by default, you can tell it to if you want), and therefore preserves all the commits just as they were made; this is quite nice, as it proves incredibly useful to be able to track the origin of changes beyond the point of a merge.&lt;/p&gt;

&lt;p&gt;When you merge two branches, it's interesting to know that none of the commits are altered in the process. Just bare this in mind for now, I'll explain why this is good to know later.&lt;/p&gt;

&lt;p&gt;After a merge, if you were to view the history, you'd see it shown like the previous example, commits in chronological order; the feature branch commits are interspersed between the master commits.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure2.png" /&gt;

&lt;p&gt;Yet no commits have been altered in the merge, so how are the commits in a different order? Well, they're not, Git's just showing you it in the order you expect it to be in. Internally the structure is still as below:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure3.png" /&gt;

&lt;p&gt;The merge commit instructs Git to walk the two trees while building the history, and it just displays the results in chronological order. This makes more sense if you recall that Git commits don't hold differences like other SCM systems, instead they each contain a snapshot of the complete repository; while in another SCM the ordering of commits is vital -- otherwise the diffs wouldn't build a valid file -- Git is able to infer order without affecting the repository contents.&lt;/p&gt;

&lt;p&gt;Looking at it in commit order, you can quite easily see how Git flattens the history to be perceived as linear without ever having to touch any of the original commits.&lt;/p&gt;

&lt;h4&gt;What happens if there's a merge conflict?&lt;/h4&gt;

&lt;p&gt;We've all dealt with conflicts in merging before. They typically happen when changes are made to the same file in two branches, in a way that cannot be easily merged (two people edit the same line, for example).&lt;/p&gt;

&lt;p&gt;Git's commit's are immutable though, so how are the changes that you need to make to resolve these conflicts saved? Simple. The merge commit is a regular commit with some extra meta-data, and so it capable of containing changes itself; merge conflict changes are stored in the merge commit. Again, no changes necessary to the original commits.&lt;/p&gt;

&lt;h3&gt;Git objects, immutability, and rewriting history&lt;/h3&gt;

&lt;p&gt;A Git repository is comprised of objects. A file is a blob object with a name attached to it; if you have two files with the same content, that's just two names to a single blob. A directory is a tree object, which is comprised of other trees and blobs. A commit is an object that references a tree object, which is the state of the repository at the time of committing.&lt;/p&gt;

&lt;blockquote&gt;To read more about git objects, I'd definitely recommend you read the &lt;a href="http://book.git-scm.com"&gt;Git community book&lt;/a&gt;.&lt;/blockquote&gt;

&lt;p&gt;Git objects are immutable. To change an object after it's been created is impossible, you have to recreate the object with any changes made. Even operations that seem to modify objects actually don't; &lt;code&gt;commit --amend&lt;/code&gt; is a typical example, that deletes and re-creates the commit rather than actually amending it.&lt;/p&gt;

&lt;p&gt;I mentioned that merges don't rewrite history, and that it's a good thing. Now I'll explain why. When you rewrite history, you do so by making changes to commits that ripple up the commit tree; when this happens, it can cause complications when others merge from you. Given a series of commits, like so:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure4.png" /&gt;

&lt;p&gt;You then share these commits with another user.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure5.png" /&gt;

&lt;p&gt;John now has Michael's commits in his repository; however, Michael notices he's made a typo in the first commit message, so he amends the commit message. The change in the message requires the commit be recreated. With that first commit recreated, the second commit now has an invalid parent reference, so that commit has to be recreated with the new reference; this recreation ripples it's way up the tree, recreating each commit with a new parent. Michael has completely rewritten his tree's history.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure6.png" /&gt;

&lt;p&gt;Notice all the commit hashes have changed in Michael's repository, and John's now don't match. If Michael was then to make a new commit to his repository, and John tried to merge that change into his repository, Git would get very upset because the new commit would reference a commit that doesn't exist in John's repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The golden rule is:&lt;/strong&gt; rewriting history is fine as long as the commits that will be affected haven't been made public.&lt;/p&gt;


&lt;h3&gt;Rebasing&lt;/h3&gt;

&lt;p&gt;The purpose of a rebase is the same as a merge, to bring two tree's of commits together. It differs in it's approach. Rebasing is a seriously sharp tool. Very powerful, but pretty easy to cut yourself with it.&lt;/p&gt;

&lt;p&gt;When you rebase one branch onto another, Git undoes any changes you've made in the target branch, brings it up to date with the changes made in the source branch, then replays your commits on top. This sounds quite strange, so I'll go over it step-by-step.&lt;/p&gt;

&lt;p&gt;You start with your diverged branches:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure7.png" /&gt;

&lt;p&gt;If you then rebase feature onto master, Git undoes the changes in master.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure8.png" /&gt;

&lt;p&gt;The history of both branches is now the same, master has been updated to reflect feature; the new commits that were made in master are now detached, floating in the repository without anything referencing them.&lt;/p&gt;

&lt;p&gt;The next step is to replay the master commits onto the new structure. This is done one-by-one, and can sometimes result in conflicts that will need to be handled like any merge.&lt;/p&gt;

&lt;p&gt;After replaying the repository will look like this:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.2/Figure9.png" /&gt;

&lt;p&gt;The master branch commits are now on the top of the stack, after the commits from the feature branch.&lt;/p&gt;

&lt;p&gt;You should recall that commits are immutable, and for changes to be made commits need to be recreated. A rebase is a destructive operation, as it has to rewrite commits to be able to work. In this case, the commits from feature have been unaffected, but the master commits have been assigned new parents (and thus rewritten). What's also noticeable is there's a lack of a merge commit, which isn't needed because the commits have been integrated into the tree; any conflicts are stored in the amended commits, rather than in a merge commit.&lt;/p&gt;

&lt;p&gt;The rewriting of commits in a rebase is what makes it a dangerous operation to perform on any branch that has already been pushed to the public (or specifically, that the changes affected by the rebase have already been pushed to the public). A rebase can cause problems upstream, like mentioned in the previous section.&lt;/p&gt;

&lt;p&gt;Rebase has it's place though. If you're working locally and haven't yet pushed your changes public, it can be a useful tool. Rebase can be used to pull in changes from upstream in the order that the upstream repository has them, and your local changes (that can be rewritten because you're the only one with them) can be replayed on-top; this is a really easy way to keep your repository up-to-date with an authoritative source. You can also use Rebase to manage local branches that you don't necessarily want polluting the history with merge markers.&lt;/p&gt;


&lt;h3&gt;When to rebase and when to merge?&lt;/h3&gt;

&lt;p&gt;Merge when you've already made changes public, and when you want to indicate that two tree's have converged. Rebase pretty much any other time.&lt;/p&gt;

&lt;p&gt;That's it for this time. Same deal as last time, if you have anything you'd like me to cover I'll nail it in the next one.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Git+guts%3a+Merging+and+rebasing&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f11%2f27%2fgit-guts-merging-and-rebasing.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f11%2f27%2fgit-guts-merging-and-rebasing.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=36170" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/git/default.aspx">git</category></item><item><title>Git's guts: Branches, HEAD, and fast-forwards</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/11/25/git-s-guts-branches-head-and-fast-forwards.aspx</link><pubDate>Wed, 25 Nov 2009 00:11:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:34984</guid><dc:creator>James Gregory</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=34984</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/11/25/git-s-guts-branches-head-and-fast-forwards.aspx#comments</comments><description>&lt;p&gt;Lets get some learning done. There are a few questions that keep cropping up when I introduce people to Git, so I thought I'd post some answers as a mini-series of blog posts. I'll cover some fundamentals, while trying not to retread too much ground that the fantastic &lt;a href="http://book.git-scm.com"&gt;Git community book&lt;/a&gt; already covers so well. Instead I'm going to talk about things that should help you understand what you and Git are doing day-to-day.&lt;/p&gt;

&lt;h3&gt;What's a branch?&lt;/h3&gt;

&lt;p&gt;I know what you're thinking. &lt;em&gt;"C'mon, we know what a branch is"&lt;/em&gt;. A branch is a copy of a source tree, that's maintained separately from it's parent; that's what we perceive a branch to be, and that's how we're used to dealing with them. Sometimes they're physical copies (VSS and TFS), other times they're lightweight copies (SVN), but they're copies non-the-less. Or are they?&lt;/p&gt;

&lt;p&gt;Lets look at it a different way. &lt;em&gt;The Git way&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Git works a little differently than most other version control systems. It doesn't store changes using &lt;a href="http://en.wikipedia.org/wiki/Delta_encoding"&gt;delta encoding&lt;/a&gt;, where complete files are built up by stacking differences contained in each commit. Instead, in Git each commit stores a snapshot of how the repository looked when the commit occurred; a commit also contains a bit of meta-data, author, date, but more importantly a reference to the parent of the commit (the previous commit, usually).&lt;/p&gt;

&lt;p&gt;That's a bit weird, I know, but bare with me.&lt;/p&gt;

&lt;p&gt;So what is a branch? Nothing more than a pointer to a commit (with a name). There's nothing physical about it, nothing is created, moved, copied, nothing. A branch contains no history, and has no idea of what it consists of beyond the reference to a single commit.&lt;/p&gt;

&lt;p&gt;Given a stack of commits:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.1/Figure1.png" /&gt;

&lt;p&gt;The branch references the newest commit. If you were to make another commit in this branch, the branch's reference would be updated to point at the new commit.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.1/Figure2.png" /&gt;

&lt;p&gt;The history is built up by recursing over the commits through each's parent.&lt;/p&gt;

&lt;h3&gt;What's HEAD?&lt;/h3&gt;

&lt;p&gt;Now that you know what a branch is, this one is easy. &lt;code&gt;HEAD&lt;/code&gt; is a reference to the latest commit in the branch you're in.&lt;/p&gt;

&lt;p&gt;Given these two branches:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.1/Figure3.png" /&gt;

&lt;p&gt;If you had master checked out, &lt;code&gt;HEAD&lt;/code&gt; would reference &lt;code&gt;e34fa33&lt;/code&gt;, the exact same commit that the master branch itself references. If you had feature checked out, &lt;code&gt;HEAD&lt;/code&gt; would reference &lt;code&gt;dde3e1&lt;/code&gt;. With that in mind, as both &lt;code&gt;HEAD&lt;/code&gt; and a branch is just a reference to a commit, it is sometimes said that &lt;code&gt;HEAD&lt;/code&gt; points to the current branch you're on; while this is not strictly true, in most circumstances it's close enough.&lt;/p&gt;

&lt;h3&gt;What's a fast-forward?&lt;/h3&gt;

&lt;p&gt;A fast-forward is what Git does when you merge or rebase against a branch that is simply ahead the one you have checked-out.&lt;/p&gt;

&lt;p&gt;Given the following branch setup:&lt;/p&gt;
    
&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.1/Figure4.png" /&gt;

&lt;p&gt;You've got both branches referencing the same commit. They've both got exactly the same history. Now commit something to feature.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.1/Figure5.png" /&gt;

&lt;p&gt;The &lt;code&gt;master&lt;/code&gt; branch is still referencing &lt;code&gt;7ddac6c&lt;/code&gt;, while &lt;code&gt;feature&lt;/code&gt; has advanced by two commits. The &lt;code&gt;feature&lt;/code&gt; branch can now be considered ahead of &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's now quite easy to see what'll happen when Git does a fast-forward. It simply updates the &lt;code&gt;master&lt;/code&gt; branch to reference the same commit that &lt;code&gt;feature&lt;/code&gt; does. No changes are made to the repository itself, as the commits from &lt;code&gt;feature&lt;/code&gt; already contain all the necessary changes.&lt;/p&gt;

&lt;p&gt;Your repository history would now look like this:&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.1/Figure6.png" /&gt;

&lt;h3&gt;When doesn't a fast-forward happen?&lt;/h3&gt;

&lt;p&gt;Fast-forwards don't happen in situations where changes have been made in the original branch and the new branch.&lt;/p&gt;

&lt;img src="http://www.lostechies.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jagregory.GitGuts.1/Figure7.png" /&gt;

&lt;p&gt;If you were to merge or rebase &lt;code&gt;feature&lt;/code&gt; onto &lt;code&gt;master&lt;/code&gt;, Git would be unable to do a fast-forward because the trees have both diverged. Considering Git commits are immutable, there's no way for Git to get the commits from &lt;code&gt;feature&lt;/code&gt; into &lt;code&gt;master&lt;/code&gt; without changing their parent references.&lt;/p&gt;

&lt;p&gt;For more info on all this object malarky, I'd recommend reading the &lt;a href="http://book.git-scm.com"&gt;Git community book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If there's anything that you're not sure about ask in the comments and I'll try get it into my next post.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Git%27s+guts%3a+Branches%2c+HEAD%2c+and+fast-forwards&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f11%2f25%2fgit-s-guts-branches-head-and-fast-forwards.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f11%2f25%2fgit-s-guts-branches-head-and-fast-forwards.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=34984" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/git/default.aspx">git</category></item><item><title>Fluent NHibernate 1.0 RTM</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/08/28/fluent-nhibernate-1-0-rtm.aspx</link><pubDate>Fri, 28 Aug 2009 12:19:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:24296</guid><dc:creator>James Gregory</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;It's &lt;a href="http://fluentnhibernate.org/downloads"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those of you that don't know, &lt;a href="http://fluentnhibernate.org"&gt;Fluent NHibernate&lt;/a&gt; is for helping you map entities with &lt;a href="http://nhforge.org"&gt;NHibernate&lt;/a&gt;. It's based firmly on the practice of &lt;a href="http://en.wikipedia.org/wiki/Convention_over_configuration"&gt;convention-over-configuration&lt;/a&gt;, and can be used in a mapping-per-class style using our &lt;a href="http://wiki.fluentnhibernate.org/Fluent_mapping"&gt;fluent interface&lt;/a&gt;, or let our &lt;a href="http://wiki.fluentnhibernate.org/Auto_mapping"&gt;automapper&lt;/a&gt; map your entities itself.&lt;/p&gt;

&lt;p&gt;This release introduces a few significant changes, and a lot of insignificant ones. You should refer to the &lt;a href="http://wiki.fluentnhibernate.org/Release_notes_1.0"&gt;1.0 release notes&lt;/a&gt; for an overview of what's changed.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://wiki.fluentnhibernate.org"&gt;wiki&lt;/a&gt; has also been upgraded to use different software which should hopefully stop people being blocked, and make it a bit more stable; the upgrade included completely rewriting all of the pages, so don't anyone say that it's out of date.&lt;/p&gt;

&lt;p&gt;You can get the binaries from the our &lt;a href="http://fluentnhibernate.org/downloads"&gt;downloads page&lt;/a&gt;, or get the source from the &lt;a href="http://github.com/jagregory/fluent-nhibernate"&gt;github site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Special thanks go out to the Fluent NHibernate team, Paul Batum, Hudson Akridge, Andrew Stewart, and Stuart Childs. Each of them has put in time and effort above what was asked of them, and they've all felt guilty when not contributing, which is great. Thanks also to all the testers and contributors we've had over the months. Specifically Darko Conrad, for finding about 30 separate issues with the release candidiate; Everett Muniz and his subclasses, who now has a test of his own; and Kevin Dente, for deciding to moan about our method names only &lt;em&gt;after&lt;/em&gt; months of work and a release candidate. I owe everyone beers if ever I'm in your area.&lt;/p&gt;

&lt;p&gt;Fabio Maulo, Ayende, and the rest of the NHibernate team: Thanks for a great tool. NHibernate is a shining example of all that is good in open source in the .Net world.&lt;/p&gt;

&lt;p&gt;...and with that, I'm going on &lt;a href="http://maps.google.co.uk/maps?f=d&amp;source=s_d&amp;saddr=Sydney&amp;daddr=Brisbane+to:Cairns&amp;hl=en&amp;geocode=&amp;mra=ls&amp;sll=-25.656382,152.880249&amp;sspn=1.383954,1.851196&amp;ie=UTF8&amp;ll=-25.522615,152.358398&amp;spn=22.065278,29.619141&amp;z=5"&gt;holiday&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Fluent+NHibernate+1.0+RTM&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f08%2f28%2ffluent-nhibernate-1-0-rtm.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f08%2f28%2ffluent-nhibernate-1-0-rtm.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=24296" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/fluent+nhibernate/default.aspx">fluent nhibernate</category></item><item><title>Preventing debugger property evaluation for side-effect laden properties</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/08/18/debugger-property-evaluation-side-effects.aspx</link><pubDate>Tue, 18 Aug 2009 11:15:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:23851</guid><dc:creator>James Gregory</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=23851</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/08/18/debugger-property-evaluation-side-effects.aspx#comments</comments><description>&lt;p&gt;Property getters with side-effects, now there's a controversial subject if ever I saw one. Don't do it is the rule; as with any rule though, there's generally an exception that proves it. If you're in this situation and you genuinely do have a scenario that requires a property getter to have side-effects, then there's a side-effect (ha!) that you should be aware of.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The debugger evaluates property getters when showing it's locals and autos windows.&lt;/strong&gt; While this feature is indispensable in most cases, it plays havoc with our property-with-side-effects. What the debugger does is call the getter to present it's value in the autos window, at the same time firing our code that has a side-effect. From there you have pretty confusing behavior with code seemingly running itself.&lt;/p&gt;

&lt;p&gt;My exception to the rule is mutator properties in a fluent interface. You can often find properties in fluent interfaces that when touched alter the behavior of the next method called.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;
string value = null;

Is.Null(value)      // returns true
Is.Not.Null(value)  // returns false
&lt;/pre&gt;

&lt;p&gt;The Is class would contain a value tracking whether the next call would be inverted or not, and the Not property would flip that value when called.&lt;/p&gt;

&lt;p&gt;Now assume this, you're using &lt;code&gt;Is.Null(value)&lt;/code&gt; and you set a breakpoint on it. Your autos window has expanded Is and shows the Not property, what's just happened? The debugger has now called Not and altered your state! Undesirable.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggerbrowsableattribute.aspx"&gt;DebuggerBrowsable attribute&lt;/a&gt; to the rescue; this attribute when used with the DebuggerBrowsableState.Never parameter instructs Visual Studio to never inspect the property you apply it to. Your property won't appear in the autos or locals window, and if you expand the tree of an instance containing the property it will show up with a Browsing Disabled message; you can then force it to evaluate the property, but at least it doesn't do it automatically.&lt;/p&gt;

&lt;pre&gt;
private bool inverted = true;

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Is Not
{
  get
  {
    inverted = !inverted;
    return this;
  }
}
&lt;/pre&gt;

&lt;p&gt;Sticking the DebuggerBrowsable attribute on your Not property prevents the debugger from hitting it and inverting the switch.&lt;/p&gt;

&lt;p&gt;So there you go, if your property-with-side-effects is being invoked by the debugger, you can use the DebuggerBrowsableAttribute to prevent it.&lt;/p&gt;

&lt;blockquote&gt;By the way, I'm not advocating properties with side-effects...&lt;/blockquote&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Preventing+debugger+property+evaluation+for+side-effect+laden+properties&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f08%2f18%2fdebugger-property-evaluation-side-effects.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f08%2f18%2fdebugger-property-evaluation-side-effects.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=23851" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/debugger/default.aspx">debugger</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/fluent+interface/default.aspx">fluent interface</category></item><item><title>Fluent NHibernate 1.0RC</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/08/16/fluent-nhibernate-1-0rc.aspx</link><pubDate>Sun, 16 Aug 2009 03:23:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:23774</guid><dc:creator>James Gregory</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=23774</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/08/16/fluent-nhibernate-1-0rc.aspx#comments</comments><description>&lt;p&gt;It's nearly here, at long last &lt;a href="http://fluentnhibernate.org"&gt;Fluent NHibernate&lt;/a&gt; has nearly reached 1.0. Now starts the official public testing of our 1.0RC.&lt;/p&gt;

&lt;p&gt;You can read the &lt;a href="http://wiki.fluentnhibernate.org/Release_notes_1.0"&gt;release notes&lt;/a&gt; on the wiki for more information on what's changed. There have been a lot of small breaking changes in the fluent interface, mostly reducing it's verbosity, and a few larger changes elsewhere. Don't expect to download this and have it &lt;em&gt;just work&lt;/em&gt;, because it won't; hopefully it shouldn't be too painful though.&lt;/p&gt;

&lt;p&gt;My plan is that this is a very quick turnaround for a release candidate. It's already undergone some heavy testing from some respected volunteers, but I wanted to get it into the public eye for a week or so before release. Ideally the RTM release won't differ from this one at all, but we'll see.&lt;/p&gt;

&lt;p&gt;You can find the binaries on our &lt;a href="http://fluentnhibernate.org/downloads"&gt;downloads page&lt;/a&gt;, and it's now included in the binary build releases too.&lt;/p&gt;

&lt;p&gt;Any questions should be directed to the &lt;a href="http://groups.google.com/group/fluent-nhibernate"&gt;mailing-list&lt;/a&gt;, and issues onto our &lt;a href="http://code.google.com/p/fluent-nhibernate/issues/list"&gt;issue list&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Fluent+NHibernate+1.0RC&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f08%2f16%2ffluent-nhibernate-1-0rc.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f08%2f16%2ffluent-nhibernate-1-0rc.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=23774" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/fluent+nhibernate/default.aspx">fluent nhibernate</category></item><item><title>Git and command-line fear</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/07/20/git-s-and-command-line-fear.aspx</link><pubDate>Mon, 20 Jul 2009 15:10:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:23107</guid><dc:creator>James Gregory</dc:creator><slash:comments>24</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=23107</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/07/20/git-s-and-command-line-fear.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://git-scm.org"&gt;Git&lt;/a&gt; has been gaining a lot of traction lately, and rightly so. I've used it for a couple of years now, for all my projects (&lt;a href="http://fluentnhibernate.org"&gt;Fluent NHibernate&lt;/a&gt; and &lt;a href="http://docu.jagregory.com"&gt;Docu&lt;/a&gt; being the prominent ones), but something that hasn't changed is the tag-line of "but Windows support isn't very good!". What you quickly learn is that when people say that, they actually mean there isn't a Visual Studio plug-in or some similar all-singing all-dancing GUI; this is a dire misrepresentation of Git, because it's tooling on Windows is excellent if your definition of tooling includes the command-line.&lt;/p&gt;

&lt;p&gt;It's something ingrained in Windows developers, they hate the command-line. There's a very good chance that if you encounter a Windows developer that does enjoy using the command-line it's because they've also worked on another platform or in another environment that encourages command-line use (Rails is a good example). I've tried various ways of encouraging people to experiment, but very few work without being able to sit down and just show them something. It's very much like R# adoption, nobody thinks it'll speed them up until they see how fast someone else can be.&lt;/p&gt;

&lt;p&gt;Back onto Git. If you don't like what Git does, then that's fine, but don't label yourself as Alt.Net or a continuous improver if this sounds like you: "I define myself by choosing the best tool for each situation, but there's no way you'll get me using the command-line." Way to go, oh open-minded one. Try it, you might like it.&lt;/p&gt;

&lt;p&gt;The other techies have been posting some great &lt;a href="http://www.lostechies.com/blogs/tags/git/default.aspx"&gt;Git posts&lt;/a&gt; which can help you get up to speed. I hope to contribute, with less bile, soon.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Git+and+command-line+fear&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f07%2f20%2fgit-s-and-command-line-fear.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f07%2f20%2fgit-s-and-command-line-fear.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=23107" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/altnet/default.aspx">altnet</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/git/default.aspx">git</category></item><item><title>Entity interface anti-pattern</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/05/09/entity-interface-anti-pattern.aspx</link><pubDate>Sat, 09 May 2009 01:35:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:20903</guid><dc:creator>James Gregory</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=20903</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/05/09/entity-interface-anti-pattern.aspx#comments</comments><description>&lt;p&gt;This has been discussed many times before on various mailing lists, and I&amp;#39;m sure there are blog posts about it that are eluding me currently, but I&amp;#39;ll put it out there anyway.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span&gt;&lt;span style="font-size:large;"&gt;Interfaces on entities are an anti-pattern&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;span style="font-size:x-small;"&gt;&lt;span style="background-color:#ffffff;"&gt;&lt;span style="color:#888888;"&gt;(when they&amp;#39;re in the vein of ICustomer and Customer)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This smells of applying a rule a little too broadly. People are (rightly) being urged to program to abstractions, to decouple and explicitly reveal their dependencies. Programming to abstractions is nearly always a good thing, but rules are often accompanied by exceptions, and in this case it&amp;#39;s entities that are the exception.&lt;/p&gt;
&lt;p&gt;Lets take a step back and remind ourselves why abstractions are useful, specifically programming to interfaces.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It lets us program against a contract, rather than a concrete implementation&lt;/li&gt;
&lt;li&gt;We can design multiple implementations of an interface, without altering dependencies&lt;/li&gt;
&lt;li&gt;We can substitute implementations at will&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Taking a typical service example, it&amp;#39;s much better for a TextWriter to depend on a IStream than it is to depend on a FileStream, because we could substitute the stream for a MemoryStream or a more high-level XmlStream without changing the design; if we didn&amp;#39;t have this abstraction we wouldn&amp;#39;t have the flexibility. A side-effect of this ability is greatly improved testability.&lt;/p&gt;
&lt;p&gt;Back to entities. Here are some tell-tale signs that you&amp;#39;re might be implementing an anti-pattern:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Your interface signature identical to your class&lt;/li&gt;
&lt;li&gt;There&amp;#39;s only one implementation of your interface&lt;/li&gt;
&lt;li&gt;Your entity has no behavior to abstract, yet you&amp;#39;ve created an abstraction anyway&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Signatures&lt;/h3&gt;
&lt;p&gt;A contract specifies what functionality an instance should provide. An implementation will rarely be of the same size (method count wise) as the contract because it will have additional code dedicated to how it provides the expected behavior. If the only thing your class does is exist purely to provide backing fields for your interface&amp;#39;s properties and methods, then it&amp;#39;s fairly redundant to have both the class and interface. It&amp;#39;s duplication for the sake of an abstraction that provides no benefits.&lt;/p&gt;
&lt;h3&gt;Implementations&lt;/h3&gt;
&lt;p&gt;Excluding cases when you have an inheritance hierarchy mapped, you won&amp;#39;t have more than one implementor of an entity interface; you&amp;#39;ll simply have ICustomer and Customer, IProduct and Product. What&amp;#39;s the point in being able to substitute implementations when there&amp;#39;s guaranteed to only ever be one? Again, a redundant design when used with entities.&lt;/p&gt;
&lt;h3&gt;Behavior&lt;/h3&gt;
&lt;p&gt;Abstraction is about allowing consumers of your object to use it without knowledge of the actual implementation. The behavior that an entity contains should mostly concern only itself (such as state changes, adding and removing children, etc...); this kind of behavior has no side-effects and can rarely vary in implementation, therefore entities don&amp;#39;t need abstractions.&lt;/p&gt;
&lt;p&gt;What about testability? With changes only affecting itself, the entities themselves can be used in tests, so there&amp;#39;s no need to mock them.&lt;/p&gt;
&lt;h3&gt;What&amp;#39;s a good example of interfaces on an entity?&lt;/h3&gt;
&lt;p&gt;Like any rule, there are exceptions; in this case it&amp;#39;s when your interface doesn&amp;#39;t fit the 3 rules mentioned above. Interfaces should be logical components that are combined to make a single unit; they can be used to contain sub-sections of behavior that are implemented by multiple entities. This design allows you to create services that depend on the specific piece of behavior, rather than an a whole entity, thus giving you a service that can be used with many entities (and ones that don&amp;#39;t exist yet) without changing the design. For example, given House, Car, and Wall classes, if each of these implemented an IPaintable interface, a service could instruct these entities to be painted without knowing (or caring) what kind of entity it was dealing with (specifically, without creating an overload for each entity type).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Don&amp;#39;t apply rules blindly, understand what you&amp;#39;re doing and why you&amp;#39;re doing it.&lt;/p&gt;
&lt;p&gt;File this one under things we all already knew.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Edit: &lt;/b&gt;Updated the behavior section to be less&amp;nbsp;controversial&amp;nbsp;(and more correct!) and added the good example&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=Entity+interface+anti-pattern&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f05%2f09%2fentity-interface-anti-pattern.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f05%2f09%2fentity-interface-anti-pattern.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=20903" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/things+we+all+already+knew/default.aspx">things we all already knew</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/orm/default.aspx">orm</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/design/default.aspx">design</category></item><item><title>What's been happening in Fluent NHibernate land?</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/04/28/what-s-been-happening-in-fluent-nhibernate-land.aspx</link><pubDate>Mon, 27 Apr 2009 23:34:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:20699</guid><dc:creator>James Gregory</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=20699</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/04/28/what-s-been-happening-in-fluent-nhibernate-land.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://fluentnhibernate.org"&gt;Fluent NHibernate&lt;/a&gt; has seen a flurry of development followed by a complete lack of commits, I figure it&amp;#39;s time to let everyone know what&amp;#39;s going on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Short Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#39;re rewriting the internals. We have 100% of tests passing, but still can&amp;#39;t guarantee no regressions. Stuff may break, if it does, &lt;a title="Fluent NHibernate Mailing List" href="http://www.lostechies.com/controlpanel/blogs/posteditor.aspx/groups.google.com/group/fluent-nhibernate"&gt;tell us&lt;/a&gt;. It&amp;#39;ll be worth it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Long Version&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Once upon a time...&lt;/p&gt;
&lt;p&gt;Fluent NHibernate at it&amp;#39;s core is a fluent interface over xml generation. We use the series of methods you call in your mappings to build up an in-memory hbm xml document that we then feed to NHibernate. Slowly, as we&amp;#39;ve started to support more and more of NHibernate&amp;#39;s features, we&amp;#39;ve started to find flaws in our architecture. It amounts to us not having enough separation of concerns; our fluent interface is generating xml, I think most people would say that&amp;#39;s not a good thing. Our xml is being generated too soon in the cycle to allow us to do more clever things that&amp;#39;d improve the user&amp;#39;s experience. That&amp;#39;s where the quiet time comes in.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.paulbatum.com/"&gt;Paul Batum&lt;/a&gt; undertook the task of redesigning the internals of Fluent NHibernate to be something much more scalable. I&amp;#39;ll leave the details out for now (maybe a future post), but it amounts to a intermediary layer being introduced between the fluent interface and the xml generation. We&amp;#39;ve dubbed this the Semantic Model, and it&amp;#39;s that which is now generated by the fluent interface, then later translated into xml. This added abstraction allows us to do things that weren&amp;#39;t possible while we were just generating straight xml.&lt;/p&gt;
&lt;p&gt;Whilst you wont see any immediate improvements while everything is being converted, the extra layer allows us to inspect the model before it is converted to xml; this gives us some immense capabilities, such as allowing subclasses to be separate from their parent mapping, create reusable component mappings, improve relationship support etc... We&amp;#39;re pretty much limited only by what we can imagine now, rather than by architectural decisions.&lt;/p&gt;
&lt;p&gt;However, we have a dilemma. The semantic-model branch has deviated so much from trunk we&amp;#39;ve got a major merge problem. A merge is pretty much out of the question actually, because there&amp;#39;s barely any commonality between the two streams at all. It was then assumed that the branch would eventually replace trunk (we&amp;#39;d just rename trunk to a tag, then rename the semantic-model branch to trunk), and all we needed to do was get the branch up-to-date with the features of trunk. Little did we realise we were essentially committing to something that I typically oppose, a complete rewrite! I&amp;#39;ve never been in a situation where that&amp;#39;s ever been a good idea, and yet here we are, responsible for our own destiny as it was, and we&amp;#39;d chosen a rewrite!&lt;/p&gt;
&lt;p&gt;A few weeks went by with very little work happening. I think we&amp;#39;d all started feeling demoralised by the idea of re-implementing most of the features from trunk using the new design. It was a worthwhile endeavor, definitely, but just very uninteresting. We repeatedly swore that we&amp;#39;d get this done, but all the while we felt less inclined to support trunk because every new feature meant a new feature to port too. We stopped.&lt;/p&gt;
&lt;p&gt;At that point &lt;a href="http://www.bestguesstheory.com/"&gt;Hudson Akridge&lt;/a&gt;, our newest contributor, had the balls to tell me that he thought what we were doing felt pretty futile. At that moment I gained a great deal of respect for him, as it&amp;#39;s something that was in the back of my mind for some time but I wasn&amp;#39;t ready to face yet. It was that which got me moving again.&lt;/p&gt;
&lt;p&gt;I sat down over a long weekend and took on the mammoth task of merging our rewrite branch and trunk, with the aim of allowing the existing code to exist alongside the new code; this approach, if it worked, would allow us to convert existing features at our own pace while still writing new features for the cleaner codebase. After a lot of unpleasant hacking of nice code, I managed to get all our existing tests passing while utilising the semantic model behind the scenes. Our old code still directly generates xml, which then gets injected into the semantic model via a nasty shortcut. It feels dirty, because I&amp;#39;ve had to comprimise some good code to get it working, but in a way I think that&amp;#39;s a good thing; if code is nasty, we&amp;#39;re all less likely to be content with it. The main goal was achieved though, and that was to allow us to work at our own pace on trunk.&lt;/p&gt;
&lt;p&gt;Where we stand now is three branches, trunk, integration, and semantic-model. Over the next day or so I am going to merge integration with trunk, which will mean the semantic model will be in use for new features. From there we can slowly migrate all the original code to use our new semantic model, all the while adding new features using it, then eventually remove the duct-tape that&amp;#39;s holding the legacy code to the new code and dump the old stuff.&lt;/p&gt;
&lt;p&gt;This is where I&amp;#39;ll give you a &lt;strong&gt;little warning&lt;/strong&gt;: although we have 100% of tests passing, we don&amp;#39;t have 100% coverage. There may be some regressions that we aren&amp;#39;t aware of. If anyone finds anything broken that was working before, contact us immediately on the &lt;a href="http://www.lostechies.com/controlpanel/blogs/posteditor.aspx/groups.google.com/group/fluent-nhibernate"&gt;mailing list&lt;/a&gt; or via the &lt;a href="http://code.google.com/p/fluent-nhibernate/issues/list"&gt;issues list&lt;/a&gt; and we&amp;#39;ll correct it. Regressions will be treated with the highest priority over any other work.&lt;/p&gt;
&lt;p&gt;That&amp;#39;s it, you now know more about what&amp;#39;s happening with Fluent NHibernate than you ever wanted to. I hope this sheds a little light onto what&amp;#39;s been happening with us, and perhaps why your patch hasn&amp;#39;t been applied as quickly as you would&amp;#39;ve liked.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=What%27s+been+happening+in+Fluent+NHibernate+land%3f&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f04%2f28%2fwhat-s-been-happening-in-fluent-nhibernate-land.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f04%2f28%2fwhat-s-been-happening-in-fluent-nhibernate-land.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=20699" width="1" height="1"&gt;</description><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/nhibernate/default.aspx">nhibernate</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/fluent+nhibernate/default.aspx">fluent nhibernate</category><category domain="http://www.lostechies.com/blogs/jagregory/archive/tags/open+source/default.aspx">open source</category></item><item><title>My name's James Gregory and I'm new here</title><link>http://www.lostechies.com/blogs/jagregory/archive/2009/03/27/my-name-s-james-gregory-and-i-m-new-here.aspx</link><pubDate>Fri, 27 Mar 2009 19:33:00 GMT</pubDate><guid isPermaLink="false">ded273ab-9e87-4979-8222-e4e2e46f1b46:20056</guid><dc:creator>James Gregory</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://www.lostechies.com/blogs/jagregory/rsscomments.aspx?PostID=20056</wfw:commentRss><comments>http://www.lostechies.com/blogs/jagregory/archive/2009/03/27/my-name-s-james-gregory-and-i-m-new-here.aspx#comments</comments><description>&lt;p&gt;Hello everybody,&lt;/p&gt;
&lt;p&gt;My name is James Gregory and I&amp;#39;m the latest convert to Pabloism!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I hail from the land of Kings and Queens, where dragons be and wenches are a-plenty. England that is, to the east in Yorkshire to be &lt;a href="http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=Gilberdyke&amp;amp;sll=37.0625,-95.677068&amp;amp;sspn=47.751524,65.830078&amp;amp;ie=UTF8&amp;amp;ll=53.752325,-0.740887&amp;amp;spn=8.984636,16.45752&amp;amp;z=6"&gt;more precise&lt;/a&gt;. I&amp;#39;ve been a developer/programmer/monkey of the code commercially for about 6 years, but I&amp;#39;ve been doing it out-of-hours for much longer. I recently quit my job to focus on personal development and open-source contributions... look where that got me!&lt;/p&gt;
&lt;p&gt;I made a vow several years ago that if I ever found that I&amp;#39;d stopped learning, I would quit the programming gig and never come back. I hope you guys will help me stick with this, if you ever find that I&amp;#39;m stagnating, please remind me of this vow.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m a pragmatist. I&amp;#39;ll use any language, any tool, any platform, whatever is needed to get the job done right. I&amp;#39;m not scared to learn, in-fact one of my most proud abilities is &lt;a href="http://blog.jagregory.com/2008/08/14/time-time-time/"&gt;being able to learn&lt;/a&gt;. I most frequently program in C# (although all my commerical jobs have always been as VB.Net developers!), I loves me some Ruby, and I&amp;nbsp;abhor&amp;nbsp;any developer who is afraid of the command-line.&lt;/p&gt;
&lt;p&gt;For those who weren&amp;#39;t subscribed to &lt;a href="http://blog.jagregory.com"&gt;my blog&lt;/a&gt; (that&amp;#39;s probably most of you) and reiterating &lt;a href="http://www.lostechies.com/blogs/jason_meridth/archive/2009/03/27/lostechies-welcomes-james-gregory.aspx"&gt;what Jason said&lt;/a&gt;, I&amp;#39;m the project lead of &lt;a href="http://fluentnhibernate.org"&gt;Fluent NHibernate&lt;/a&gt;, which is a strongly typed alternative to NHibernate&amp;#39;s XML mappings (and much more). I&amp;#39;m also the lead for &lt;a href="http://docu.jagregory.com"&gt;Docu&lt;/a&gt;, a simpler documentation generator for .Net projects. These will certainly make up a large part of my bloggings, but hopefully not the entirety.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m&amp;nbsp;incredibly&amp;nbsp;pleased to be a part of Los Techies, and I hope I don&amp;#39;t bring down the tone too much.&lt;/p&gt;
&lt;p&gt;You can find me on Twitter as &lt;a href="http://twitter.com/jagregory"&gt;jagregory&lt;/a&gt;, skype as jagregory.com, gtalk and email at: james at jagregory dot com. Feel free to get in touch if you think there&amp;#39;s anything I can do for you.&lt;/p&gt;
&lt;p&gt;That&amp;#39;s enough about me!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;a href="http://www.dotnetkicks.com/kick/?title=My+name%27s+James+Gregory+and+I%27m+new+here&amp;url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f03%2f27%2fmy-name-s-james-gregory-and-i-m-new-here.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.lostechies.com%2fblogs%2fjagregory%2farchive%2f2009%2f03%2f27%2fmy-name-s-james-gregory-and-i-m-new-here.aspx" border="0" alt="Kick It on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;img src="http://www.lostechies.com/aggbug.aspx?PostID=20056" width="1" height="1"&gt;</description></item></channel></rss>