bling.github.io

This blog has relocated to bling.github.io.
Showing posts with label Source Control Management. Show all posts
Showing posts with label Source Control Management. Show all posts

Sunday, December 5, 2010

Working in Git to Working in Mercurial

I took the dive a couple weeks ago and learned how to use Git and fell in love with its simplicity.  I don’t know what it is, but after using Git every day it actually started to make sense that git checkout is used for so many things, which is ironic because prior to using Git, every introductory tutorial I’ve read has always had me thinking, “checkout does what and what and what now??”.

So why did I switch to Mercurial?  I need to push/pull from a Subversion repository, and I work on Windows.  General day to day work is great, but when I needed to git svn rebase or git svn dcommit it would take so long that I simply left to get coffee.  What’s worse, no matter what I set for core.autocrlf I would always get some weird whitespace merging error, when nothing was wrong.  It became a regular part of my workflow to just git rebase –skip everything because that’s what fixed things.  Scary.

The crappy Subversion and whitespace support (at least in Windows) led me to try Mercurial.  After getting accustomed to Mercurial, they’re actually a lot more similar than they are different.

First things first, you need to add the following to your mercurial.ini file in your home directory:

[bookmarks]
track.current = True

Here’s a comparison of my typical Git workflow translated to Mercurial:

  Git Mercurial
Work on a new feature/bug git checkout –b new_feature hg book new_feature
Hack hack hack git add .  
Commit git commit –m “done!” hg commit –m “done!”
Hack more and commit git commit –a –m “more hacking” hg commit –m “more hacking”
Sync with up stream git pull master hg pull
Merge git checkout master hg merge new_feature
  git merge new_feature hg commit –m “merged”
Push git push hg push

Notice that they’re practically exactly the same?  There are some minor differences.  The obvious one being that you need to add into git’s index before committing.  And the other I didn’t have to switch branches in Mercurial (more on that later).  But aside from that, it’s pretty much the same, from a user’s point of view.  Check this fantastic thread on StackOverflow for one of the best comparisons on the net if you want to dive into technical details.

So far, there are only two things that bother me having switched:
  a) No fast-forward merge.  You need to manually rebase and then commit.
  b) No automatic commit after a conflict free merge.

These are fairly minor annoyances, but can be scripted/aliased away.  Or if you don’t like those defaults in Git, you can override them in the command arguments or set them in gitconfig.  Mercurial similarly can change default arguments in its hgrc/mercurial.ini.

One of the biggest advantages of Git is easily switching between all its local lightweight branches at lightning speed.  Tangled source code is no more!  I was confused with Mercurial’s bookmarks when I first used them because all it does is label your head with something.  I don’t know why this is, but it is the same as git checkout –b, but for some reason I visualized Git “branching” the latest commit into two paths.  But how do you do that if they’re the same?  It should only branch after a commit which introduces changes, which is what Mercurial does.  In this scenario, Mercurial is more explicit, whereas Git is implicit.

Using bookmarks, you can mimic Git’s workflow like this:

  Git Mercurial
Create a bunch of ‘working areas’ git branch feature1 hg book feature1
  git branch feature2 hg book feature2
Switch/commit/hack/commit git checkout feature1 hg up feature1
  git commit –a –m “feature1” hg commit –m “feature1”
  git checkout feature2 hg up feature2
  git commit –a –m “feature1” hg commit –m “feature2”
Sync up stream git pull master hg pull
  git checkout master hg up default
Merge in 1 feature git merge feature1 hg merge feature1
    hg commit –m “merged”
Delete branch/bookmark git branch –d feature1 hg book –d feature1
Push git push hg push –r tip
Switch back and hack again git checkout feature2 hg up feature2

The –r tip switch on hg push might have raised an eyebrow.  This is to tell Mercurial to push all changes that lead to the tip.  This will include the changes in feature1 that we just merged in, but exclude all the ones in feature2.  If you issue a hg push it will complain and warn you that you’re going to create multiple heads on the remote repository.  This is not what you want since there may be unfinished features, experimental branches, etc.  Of course, you can force it anyways, but that’s not a good idea.

At first, the tip was most confusing to me because I tried to associate it with Git’s master, which was simply not the case.  Tip refers to the newest change that you know about.  This can be on any branch or bookmark.  Once I understood that, and stopped trying to create a Git master equivalent, everything was straightforward.

So let’s start with an example.  First I create a bookmark feature1 after syncing, and then making a commit looks like this:

image

And then if you switch to feature2 and make a commit, it becomes like this:

image

Here’s where you start thinking, “I don’t have a master which tracks upstream changes, how do I separate my local changes?”  And now here’s a situation where Mercurial does more black magic than Git.  If there are up stream changes, after issuing hg pull, this happens:

image

Mercurial automatically split my local changes into their own separate branches (actually, heads is the accurate term).  After this operation, tip is now tracking the changes that I just pulled in from upstream, instead of my bookmark.

From here, it’s simply hg up tip to switch to the “master” branch.  Then a hg merge feature1; hg commit, and it becomes like this:

image

Then it’s simply hg push –r tip, and you’re good to go.  Basically, if you bookmark every feature/bug you work on, then you should only have one branch that doesn’t have a bookmark, which is the same as the ‘master’ branch from Git.

What about Subversion?

Whoops, forgot why I switched in the first place.  First, install hgsubversion, after that’s set up, simply:

hg clone http://path/to/subversion/repository

And then it’s just hg pull or hg push.  Is it really that simple?  Yes, yes it is.

Saturday, April 25, 2009

SourceGear Vault, Part 4, Conclusion

I suppose I should give a disclaimer since I am *not* an expert with Vault, and my opinions may be completely due to my lack of understanding of the system. With that in mind, here's what my experience of using Vault has been so far. In general, it is not as fast as TortoiseSVN. There are many operations in SVN that are instant, where the comparable operation in Vault is met with 10 seconds of "beginning transaction" and "ending transaction", sometimes more. Feature-wise, Vault has much more to offer than Subversion does. Basically, it can do most of what Subversion can do, plus features from SourceSafe (like sharing, pinning, labeling, etc.). However, like I mentioned before, Vault has no offline support whatsoever, and you cannot generate patches, so it effectively cuts off any kind of outside collaboration. You could say that this is fine because SourceGear's target audience is small organizations where everyone will have access to the network anyway, but that doesn't mean that you won't be sent off to the middle of nowhere with no internet access and you need to fix bugs now! Not to say that Subversion is much better in that scenario, but at least you can still revert back to the last updated version.

Friday, April 24, 2009

SourceGear Vault, Part 3 (Performance vs Subversion)

I downloaded the kernel 2.6.29.1, and extracted it to the working folder. I figured this was an easy way to have a real-world scenario of changes (albeit a little big since it is all changes that happened between 29 and 29.1). Anywho, I was pretty surprised to find out that Vault does not have any feature whatsoever to allow collaboration between programmers other than via the client. You cannot create a .patch file and email it to someone. Everyone is assumed to have access to the server. This thwarted my plans to test the performance of diffing the changeset, because I simply planned on comparing how long it would take to create the patch. Ah well, I guess I'll just have to compare the performance of committing the changes between 29 and 29.1, which is a common use case as well so I don't mind. Time it took to a) start up the Vault client, b) bring up the Vault commit dialog, or c) bring up to TortoiseSVN commit dialog: Vault startup: ~1m02s Vault commit: ~7m55s Subversion commit: ~4m33s Time it took to commit: Vault: ~13m45s, and at 14m34s the HD stopped spinning Subversion: ~1m42s Hmmmmm, it doesn't look like Vault did too well in this comparison. Getting a status of all changed files took almost twice as long compared with Subversion, and what's worse, committing with Valut took 12 minutes longer than it did with Subversion. The extra minute with the hard drive spinning was attributed to SQL Server completing the transaction, which is why I separated that part, because as far as the client was concerned the operation was complete after 13m45s. One more quick test...branching. Subversion is famous for its O(1) time to branch anything, from the smallest to the biggest. SourceGear's page of Vault vs Subversion mentions that both offer cheap branches. Let's see that in action! I used TortoiseSVN's repo-browser and branched the kernel. It was practically instant with no wait time for the operation to finish. Vault, on the other hand, took a total of 47 seconds from the time it took me to commit the branch, to when the status said "ready" again.

Thursday, April 23, 2009

SourceGear Vault, Part 2 (Performance vs Subversion)

Obviously you can't compare something without performance numbers! So in this post I'll post some performance numbers for the most common operations. I'll be using the Linux kernel for no reason other than it's readily available and everyone knows about it. The size of the code base is also relatively large (depending on who you ask). In general, I "felt" that Vault is slower than Subversion. This is probably due to the .NET runtime startup time for most operations, which is negligible for anything but trivial operations. Test environment: Core2Duo clocked at 3.6GHz 4G of RAM Vista 64bit/IIS7/SQL2008Express Vault 5.0 Beta 1 (I'm hoping the beta isn't going to affect performance numbers drastically) TortoiseSVN 1.6.1 Linux kernel 2.7.29 (roughly 300MB of source code and more than 26000 files) Both server and client are on the same computer, so none of these scenarios will really test network performance. Anyway, on with the tests. Time it took to recursively add all folders and files and just bring up confirmation dialog Vault: ~14s Subversion: ~11s Time it took to mark all files to add (create a changeset): Vault: 0s (it was pretty much instant) Subversion: ~6m52s Time it took to commit: Vault: ~21m10s Subversion: ~28m50s Total: Vault: ~28m16s Subversion: ~35m53s As you can see, Vault was slightly slower at a trivial operation like which files to add, but once it got to some real work to do, it ended up being faster overall vs Subversion. A significant part of the Subversion time was devoted to creating .svn folders. After this, it was apparent that Subversion has a pretty major advantage over Vault...working offline. Vault does not appear to keep any offline information. This was confirmed when I went into offline mode in Visual Studio and pretty much all functionality was disabled except for "go online." Basically, when you're working offline in Vault you can no longer diff with the original version, no reverting changes, no anything. Once you go online it scans your working copy for any changes and the "pending changes" will update. I don't like super long posts, so there will most definitely be a part 3 where I'll continue on with some common operations.

Wednesday, April 22, 2009

SourceGear Vault, Part 1

I'll be starting a new job soon, and the company is using SourceGear Vault, so I went ahead and downloaded the latest beta versions off the site (since it's free for single users) to see how it was like. I've hated SourceSafe from the first time I used it. The nail in the coffin was when my data got corrupted and some of my work was lost. At the very least, no source control management system should ever lose any work. Unfortunately, my current workplace is still using SourceSafe and I was unable to convince them otherwise. I've coped with the situation by using Mercurial for a quick local repository, and checking in changes back to VSS for major changesets. The choice to go with hg instead of git or bzr was mainly because I'm a Windows developer and hg is currently way ahead of the other two on Windows. Anyways, since Vault is frequently advertised as SourceSafe done right, I was curious to how it would affect my opinion of how things "should" have worked. I'm a long term user of Subversion, and most of my experience of actually using SCM is with svn. I used hg at work just to see what all this DVCS hype is all about. With that in mind, setting up Vault was certainly more eventful then I expected, since it involved setting up SQL Server and IIS. After all the requirements were taken care of (the most time consuming part), installing Vault was pretty quick. The administration interface is simple and straightforward, and had a repository created by default. Then, the real fun began! Tune back for part 2!