@Shazwazza

Shannon Deminick's blog all about web development

A quick UI guide to using Umbraco’s new repository format: Mercurial

December 15, 2010 17:19

If you haven’t read the news, Umbraco is moving it’s repository format from TFS to Mercurial today! The Umbraco post lists quite a few links to start learning about Mercurial and how it works and I definitely recommend reading them!  Aaron from the Core team has also put up some blog posts:

This post is going to show you how to get up and running quickly with Mercurial and the Umbraco source using 2 UI tools: TortoiseHg and VisualHg.  So first thing is first, make sure you download these 2 applications and get them installed.

Using TortoiseHg

Initial setup

If you are familiar with TortoiseSVN then this should seem reasonably similar to that. TortoiseHG, like TortoiseSVN, is an application that is accessed by a context menu in Windows Explorer. An important thing to note about TortoiseHg is that there’s settings, both on a global level and on a repository level. If this is the first time you’ve used TortoiseHg, then it might be a good time to set up some global defaults:

Global settings can be found by right clicking a folder –> TortoiseHg –> Global Settings

image

 

Here’s some defaults that I recommend setting up on a Global level:

Change the default Diff tool

This is my own personal preference, but the default diff tool is called KDiff3 which I find horribly ugly and difficult to use… up to you though. I’m currently a fan of DiffMerge which is an awesome free diff tool that does both file and folder diffs, plus it looks nice and is extremely simple to use. Once you install a default diff tool it should show up in the drop down lists for: Three-way Merge Tool and Visual Diff Tool

Set your default username

Again, you don’t have to do this but since my username for most of the Mercurial accounts is the same, I set it here. This is also the name that will be associated to any change sets that you commit.

Clone the source

Ok, time to get the code! First thing is to create a folder where you want to store the repository. Since Mercurial is a DVCS you need to actually download the entire repository (aka CLONE). This will download all changesets, branches, tags, etc…. This might sound like a lot but when dealing with blocks of code, it's generally relatively small (NOTE: there are extensions and tricks in Mercurial that allow you to not have to clone the entire repository, but we’ll let you research those! ). Once your folder is created, right click –> TortoiseHg –> Clone…

The only thing that is required to clone the repository is to enter the source address, as seen below:

image

Once you clone the source, this will automatically update your latest working folder the the ‘Tip’ which is the latest committed change set in the repository, however there’s an option listed on the Clone dialog to disable this behavior if you don’t want that to occur (as seen above). This can be useful if you want to clone a repository but have your working copy updated to a specific revision or branch. In this example, we’ll update our working copy manually since there’s a few active branches in the Umbraco codebase and we’re not sure which one the ‘Tip’ will be. Once the clone is complete, you can either use the Update context menu option, or use the Repository Explorer.

Update Dialog

The update dialog is a quick way to update your working copy to the latest revision of a specific branch or tag. This is pretty straight forward, just select the branch/tag you want to work from and click Update. NOTE: there are a couple of advanced options:

  • Discard local changes – don’t leave this checked unless you mean it. This will remove any local changes you may have made is completely replace them with what's in the branch
  • Always merge – a pretty good idea to have this checked so the merge dialog will show when it detects conflicts
  • Always show log – if you want to see some log info, check it

Repository explorer

The Repository explorer is probably where you’ll spend most of your time working with Mercurial (at least I do). From here you can run most of the commands that you need: Pull, Update, Commit, Push & Merge though there’s a few ways that you can do each one of those from the various menus. The repository explorer shows you the history of all of the checkins including date/time, the user who did it, which files were modified/added/deleted and will even show you a nice diff/patch view of each changed file.  The UI gives you a bunch of tools to filter the list of change sets that are visible such as filtering by branches or searching for revisions, users, etc…

image

Merging

Merging in Mercurial is actually really easy, as compared to some other version control systems and it happens reasonably often if more than one person is working on the source at one time (which is generally the case). Merging can easily be done from the Repository Explorer and you’ll know when you have to merge. Here’s when

  • You try to push your committed changesets to the server and TortoiseHg starts complaining about create multiple remote heads in the repository. This means that you need to do a pull and get the latest revisions.
  • Or, you’ve done a pull and can see that there’s newer revisions in the graphs

So all you need to do is open the Repository Explorer (as seen above), right click the revision that you want to merge with and click “Merge with”. If there’s any conflicts, it will launch your Diff tool. Once you’ve merged, it will ask you to commit the changes which you can cancel if you want to manually fix any conflicts.

Local Repository Settings

As mentioned before there’s both global and local repository settings. To get to the local settings:

Repository Explorer –> Tools –> Settings

Save your repository password

One thing I always do so that TortoiseHg doesn’t prompt you every time is save the password for your repository. You can do this from the local repository settings –> Synchronize –> select the ‘default’ item in the Remote Repository Paths (this should have been automatically created when you first cloned the repository) and select edit.

image

Using VisualHg

VisualHg is a source control plugin for Visual Studio which does what you would expect:

  • Automatically ensures that files are added to source control when you create a file
  • Automatically handles renaming/moving files in source control when you move/copy files in the solution explorer
  • Has handy colored icons for each file to show you what’s changed, renamed, etc…
  • And additional context menu items for items in your solution explorer which are quick links to the TortoiseHg interface:
    • Commit
      • Launches the commit dialog
    • Status
      • Shows you the history of particular files, allows you to revert to specific revisions, etc…
    • History
      • Launches the Repository Explorer
    • Synchronize
      • Launches the Synchronize dialog allowing you to Push/Pull your changes from CodePlex
    • Update
      • Launches the Update dialog
    • Diff
      • Launches the default Diff tool

Activating VisualHg

Since you might already have TFS (or other) configured as your primary source control plugin for Visual Studio, you might need to tell Visual Studio to you VisualHg instead when working in the Umbraco repo. This is really easy and you don’t have to restart Visual Studio either. Just go to:

Tools –> Options –> Source Control –> Select VisualHG from the drop down list

That’s it!

Final thoughts

There’s a TON of functionality in Mercurial and I mean A LOT. Aaron’s posts talk a lot about the command line and it’s good to become familiar with it since if you want to do more complicated things like using the extensions (which can be enabled on the Global or Local Repository settings), then this nearly all has to be done from the command line. There’s also a lot of functionality that you can do with these UI tools that I haven’t talked about such as branching, creating patches, exporting bundles, serving your own repository server over a web port, shelving changesets, and lots more. So go explore!

Importing SVN to Mercurial with complex SVN repository

November 2, 2010 21:14
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
Here @ TheFARM, we’ve been moving across to Mercurial (on BitBucket) for our code repositories. In many cases our SVN repositories are structured ‘normally’:
  • trunk
  • tags
  • branches

Using the ‘hg convert’ command line, when your SVN repository is structured this way will import your trunk into the Mercurial ‘default’ branch and your branches/tags into named branches. This also imports all history and revisions. From there, you can merge as you wish to structure your Mercurial repository the way that you want.

However, in some cases we have more complicated repositories. An example of this is a structure like the following:

  • trunk
    • DotNet
    • Flash
  • tags
  • branches
    • v1.1-DotNet
    • v1.2-Flash

In the above structure, we’ve actually branched the trunk/DotNet & trunk/Flash folders separately into their own branches. Unfortunately, Mercurial doesn’t operate this way so it doesn’t really understand creating branches from folders. There’s a couple different ways that you can get this from SVN into Mercurial whilst maintaining all of your history…

One way is to run ‘hg convert’ on the entire repository. You’ll end up with 3 branches in Mercurial: default, v1.1-DotNet & v1.2-Flash. The problem is that if you try to merge the named branches into default, you’ll end up with a mess since the branches don’t have the same folder structure as default. To overcome this, you can restructure each named branch to follow the same folder structure as default. To do this, we us the ‘rename’ method on Tortoise Hg. So for instance, if we had this folder structure inside of v1.1-DotNet:

  • BuildFiles
  • MyProject.Web
  • MyProject.Config

So that we can merge this with default we need to restructure this into:

  • DotNet
    • BuildFiles
    • MyProject.Web
    • MyProject.Config

So we just need to right click each folder seperately, and select the rename option from the Tortoise Hg sub menu:

image

Then we prefix the folder name with the new folder location which will the ‘move’ the file:

image

Now that the named branch v1.1-DotNet is in the same folder structure as default, we can perform a merge.

The other way to import a complicated SVN structure to mercurial is to convert individual branches to mercurial repositories one by one. The first thing you’ll need to do is run an ‘hg convert’ on the Trunk of your SVN repository. This will create your new ‘master’ mercurial repository for which will push the other individual mercurial repositories in to. Next, run an ‘hg convert’ on each of your SVN branches. For example: hg convert svn://my.svn.server.local/MyProject/Branches/v1.1-DotNet.

Once you have individual repositories for your branches, we can force push these into your ‘master’ repository. To do a merge of these branches, the above procedure will still need to be followed to ensure your branches have the same folder structure as default. HOWEVER, because we’ve forced pushed changesets into Mercurial, it has no idea how these branches relate to each other (in fact, it gives you warnings about this when you force push). When you try to do a merge, you’ll end up getting conflict warnings for every file that exists in both locations since Mercurial doesn’t know which one is newer/older. This can be a huge pain in the arse, especially if you have tons of files. If we assume that the branch files are the most up to date and we just want to replace the files in default, then there’s a fairly obscure way to do that. In the merge dialog, you’ll need to select the option “internal : other” from the list of Merge tools:

image

This tells Mercurial that for any conflict you want to use the ‘other’ revision (which is your branch revision since you should have default checked out to do the merge).

We’ve had success with both of these options for converting SVN to Mercurial and maintaining our history.