Merging with Mercurial

I've got a project at work where I am tempted to use Mercurial as a front end to SVN just so I can make use of its reported advanced (compared to subversion) merging capabilities. This is a quick look to see how this merging works, first natively, then against a SVN bridge.

I'm going to be using VisualHG 1.0.9 , tortoiseHG and hgSubversion to do all of this.

First we need source code to diff, so I'm going to simply create a base application then make lots of changes to. The idea will be to make this changes as separately as possible, then start merging those changes together. In particular I want to confirm in Hg is clever enough to track changes across file renames and refactorings.

A simple WPF app

First lets create a simple WPF application, then convert it to MVVM with some fairly basic common functionality. My first check in is literally a New WPF application straight from the Visual Studio 2010 New project wizard.

clip_image002

Issue #1

Now the first issue I came across was that the solution file has not been detected by VisualHG as a component of this solution, only the project and files.

clip_image004

This was incredibly easy to resolve, which makes me wonder why it wasn’t detected. I realise this is more likely to be an issue with Visual HG or Visual Studio than tortoiseHG or Mercurial itself.

Initial commits

Initially I'm just committing the original template, and adding the solution (See Ignore filters). This gives the initial DAG (part 1, part 2) shown.

clip_image006

Introducing conflict

We now need some changes that conflict, so every change I describe below is performed in a manner that causes branching.

Solution rename

First lets rename the solution, and commit that. Then I roll back by selecting the previous version and updating back to that version.

clip_image008 

Introduce folders in Project

My next check in causes a the DAG to stop being a line. Note the text on the commit dialog telling you that you are about to produce a new head to your development. The important point here is that there are changes to the .csproj file.

clip_image010 clip_image012 

image

Hello World MVVM

Once again I’m going to roll back by updating back to Version 1. My next change provides a little functionality and will modify files that have just been modified in a different branch/head. I’m introducing a new file RootViewModel.cs but I have to add this in the root.

 

image image image

This change is a little naive, as it doesn’t place the files on disk in the correct location. However by merging in the previous change, we can pick up those folders and then move the files around.

Quick guide to merge

If you look at the Repository Explorer then you see that your current version of the source code is displayed in bold and underlined. You can select any other version with a click, and then you are just a right click away from updating to that version or as in this case, merging it into the version you currently have.

image

Once you have selected Merge With.. the next dialog that you see confirms the versions that you are combining. Just hit ok.

image

One thing I really like about Mercurial is just how descriptive the messages are. It really makes it difficult to make a mistake. It also provides the commit button on the UI ready for you.

image

Pressing that button takes you into the straight into the Commit window, it pre-populates the comment with “merge” and shows you exactly what has changed. I note that this time the Commit button indicates that you are going to remove a head. Unsurprisingly therefore the DAG now shows a reduced head as we can see below in the centre. The view in Visual Studio is now shown on the right.

image image image

Obviously my next change would be to relocate the files into the correct location. I can do this in Visual Studio by simply dragging the files, because VisualHG knows what changes are happening. This is shown with an R to indicate a rename, and if you look in the Commit window, you can see what Mercurial is recording behind the scenes.

image image

Which leads to a repository view like this.

image

Back to making it awkward

Now I want to test Mercurial’s ability to track changes, so I now am going to roll back again to version 4, where I introduce the RootViewModel class. This test maps to another developer making a change at the same time as other work carries on.

image image image

Now here’s the theory. If I merge this change into the one where I’ve already moved my file, then my commits should be applied to the relocated files. I need to merge to test this out.

In this case I am going to update my view of the code to the one where the files have already been moved, i.e. Rev 6, and then merge in Rev 7. I’m trying to make sure it tracks the change, instead of just updating the file. You’ll also notice a quick fix to my demo project on the way.

 image  image

image

This works flawlessly. Which is really surprising if you are used to SVN.

What Mercurial can’t handle

I’ve taken the this one step further and applied a common refactoring. I start with a broken piece of code in my Model, note this produces “World Hello” as a Title.

public class RootModel
   {
       public string Title { get { return String.Format("{0} {1}", Noun, Verb); } }

       public string Noun { get; set; }
       public string Verb { get; set; }
   }

If I refactor the Title property out from the Model to the ViewModel in one change, and in a separate change I fix the order of Noun, Verb to Verb, Noun, then I find that Mercurial can’t handle this. 

Add comment

  Country flag


  • Comment
  • Preview
Loading