Not sure if this is anything you don’t already know, but I’ve been using mercurial locally for a little while now, and so far I think the benefits are outweighing the added overhead of managing the two source control systems. Here is how I’ve been doing things:
-
I made my TFS checkout an HG repository which I consider my “master”. I get updates from TFS and commit them to this repo, so this contains the most current state of the project from TFS. The important thing here is that there are no changes to this made independent of a TFS update or an Hg merge (which is part 2)
-
Anytime I need to make a change, I clone my “master” repo and do my work there. I’ve found that a clone per feature or story is actually pretty easy to manage, and feels pretty clean. Once I complete a feature, I do an Hg merge back to the “master” repo, which has had all of the TFS updates applied. This allows me to use Mercurials merge capabilities, which are so far superior to TFS as to call into question how TFS can claim to merge code at all. Once the merge is complete, I commit it in Hg, and then check those changes into TFS. The best part of this is that when I do the checkin to TFS, I do not have to merge anything. Very, very nice.
Now, here are the issues I’ve found with this approach:
-
The biggest is the fact that TFS is lousy at finding changes. There is a make writable plugin which you can use to make the modified files writable when they are updated/merged by Mercurial. There are two options I have found for this. You can either force TFS to go offline, at which point it will assume anything writable needs to be checked in, or you can use the compare tool in the source control tool and select the changed files and individually check them out. Both are crappy IMO
-
The source control bindings are still there at the project level, even if you exclude the TFS source control files from your hg repository (which you should do). This isn’t entirly obvious until you add a file to the solution, at which point it tries adding it to source control. You can “Undo Pending Changes” and get rid of the source control add, but it’s really annoying.
The good news is that I used this approach to work through a rather massive merge which I think would have caused me to turn to some form of hard drugs had I been forced to use the TFS tools to do it.
I have not yet applied this to updating branches within TFS, but my guess would be that it would be much much better than the options you are given for merging in TFS. On a related note, since you can check in chunks of working functionality at one time, using the TFS merge would be less problematic just because all changes needed for a feature would be together in one place.
One thing I have not tried to tackle is sharing this across the entire team. Part of the reason is that it really doesn’t have to be a team-wide thing. I work remotely, so having a local repository is a big deal, and saves a lot of time. The other members of my dev team may or may not get the same benefit from this approach, but I find it pretty cool that I can without effecting the way they work.
Update
I’ve been wanting to update this response for a while with additional info based on comments and some of my experiences working with large TFS repositories.
First as @Eric Hexter points out in the comments, you can utilize the rebase extension to better integrate commits from your work repositories into your main TFS repository. Though, depending on how you want your commits to appear to TFS you may want to use the collapse extension to squash your changes into a single commit (this can make rollbacks in TFS easier). There is also the “online” command from TFS PowerTools which can make the work of letting TFS know what has changed easier (thanks again to Eric for mentioning that in his blog post)
Now, when I originally wrote this I was working on a project that had only one TFS branch that developers were using, and was fairly small, so cloning repositories was no big deal. I later found myself working on a project that had a repo that was about 1.5GB after checkout, and much bigger after the build, and involved switching between branches in TFS quite often. Clearly this approach is not well suited to this environment (particularly since at one point it was impossible to build the solutions in an arbitrary directory.
The size problem is best handled by utilizing a technique similar to gits topic branches rather than cloning the repositories to new directories. There are a couple options for this. I think the best is actually to use the bookmark extension and create topic “bookmarks” rather than topic branches. You can use named branches as well, but they have the slight disadvantage of being permanent, and traveling with any clones you may do (if you want to share your nifty TFS-Hg hybrid with a colleague). Bookmarks are local to your repo, and effectively point to a commit and travel with the head. They are implemented so that they can be used in any place where Hg is expecting a revision (so merges, updates, etc). You can use these to create a TFS bookmark as your primary “branch” that only gets updates from TFS, and merges from the topic work, which would each have their own bookmarks, and you could delete once you have committed back to TFS. If you would rather use named branches, then you can apply exactly the same techniques, which is handy.
Now, the multiple branch problem is trickier, especially since TFS “branches” are actually copies of every file from the original branch, which means that each time you pull in branches from TFS, your repo is going to get that much bigger. One possible way to deal with this is use a combination of named Hg branches, and bookmarks, so that you have a branch for each TFS branch, and then create bookmarks for your work off of those branches. The real headache in these scenarios is actually dealing with TFS workspaces through all of this. You can remove the mappings in your workspaces and get pretty far, but once you map back to your working directory you’ve got to be careful of TFS stomping on files (this is actually where the TF PowerTools come in handy). Trying to leave the workspace attached while your switching branches around gets ugly quick. A couple tools that are nice to have in your toolbelt are the Hg purge extension and the TF PowerTools “scorch” command. Both effectivly remove files that are not in version control (technically “scorch” ensure TFS and your local working directory match, so it could update files as well).
For me, though, this process became quite burdensome and error prone. I’ve recently switched to useing git with git-tfs, since it manages TFS Workspaces for me, and removes a lot of the burden associated with that side. Sadly there does not appear to be an “hg-tfs” out there anywhere, or I would probably have chosen that.