I’m writing some sort of new adminstration dashboard for our cms (which runs on asp.net webforms). Some of our older servers can only handle .NET 2.0 for various reasons so I’d have to rewrite my code which uses lambda expressions etc. for that.
I wonder how you would use a dvcs like mercurial to develop those two versions concurrently.
My current codebase and mercurial repository is targeted at .NET 3.5. I’m relatively new to mercurial and I guess I’d have to branch the codebase?
Any best practices or tutorials?
Yes, you can use Mercurial for this. Here is how it would work.
Let’s say that your current clone is called
new-dot-netsince itsupport the new .Net version. You make a clone of it and call it
old-dot-netor something like that. The two clones are now identicaland both target .Net 3.5.
Now carefully make small changes in
old-dot-netin order to make it.Net 2.0 compatible. When you make the changes the two clones will
start to diverge:
Here you made
[c]and[d]changesets to add the .Net 2.0compatibility. Notice how the
old-dot-netclone contains morechangesets than
new-dot-netsince it has the backwards compatibilitychanges that you dont want to see in
new-dot-net. As you continueworking, it is important to think of this:
net-dot-netwill containa subset of the changesets in
old-dot-net. The changes flow fromnew-dot-nettoold-dot-net, but never in the opposite direction.Let’s say you make a new change in
new-dot-net. You make the changein
new-dot-netand the situation now looks like this:You now want to back-port the change to
old-dot-netas well, youchange to
old-dot-netand pull fromnet-dot-net:This will create a new head in
old-dot-net:[x] / old-dot-net: ... [a] --- [b] --- [c] --- [d]since the
[x]changeset has[b]as it’s parent changeset. You nowhave multiple heads and have to merge to reduce the number of
heads. By merging you create a new changeset which is your way of
saying “this is how
[x]and[d]should be combined”. If the[x]changeset only touches code which is not also touched in
[c]and[d], then the merge should just work. Otherwise you’ll be presentedwith a merge tool and have to resolve the conflict. You commit the
merge as chageset
[e]:[x] --------------. / \ old-dot-net: ... [a] --- [b] --- [c] --- [d] --- [e]And you’re done — you have now incorporated the
[x]change intoyour .Net 2.0 compatible code.
You repeat this every time there has been a change in
new-dot-net.Let’s say that more features are added:
After pulling them into
old-dot-netyou get[x] --------------.---- [y] --- [z] / \ old-dot-net: ... [a] --- [b] --- [c] --- [d] --- [e]And you now merge
[e]and[z]:[x] --------------.---- [y] --- [z] / \ \ old-dot-net: ... [a] --- [b] --- [c] --- [d] --- [e] ----------- [f]The important parts to remember are these:
new-dot-net.old-dot-netold-dot-nettonew-dot-net.Should you at some point find that a change in
new-dot-netis notneeded in
old-dot-net, then you still need to pull it in and mergeit. But you will then do a dummy merge. If the heads are
[w]and[g], and you want keep[g], then doThe trick is to do the merge without caring about the results,
then revert all changes, and commit the unchanged working copy as the
merge. That way you tell the world that “the combination of
[w]and[g]is[g]“, i.e., you throw away the changes in[w]. Newchanges made in
new-dot-netafter[w]can then be merged likenormal.