Git and Mercurial side by side

Though many sources describe distributed version control systems as having no central storage the truth is that most projects do have a central repository. The difference compared to a traditional version control system like Subversion or CVS is that you also have a local repository and commits are done in two stages. First you commit your changes to your local repository, then you push those changes to the central repository.

The two biggest distributed version control systems today are Git and Mercurial. I’m going to describe them here by using them in a short test and comparing them side by side. The command line command for Mercurial is hg, from the chemical symbol for mercury.

git clone https://Gieron:Password   hg clone https://Gieron:Password
      @github.com/Gieron/test.git         @bitbucket.org/Gieron/test
cd test                             cd test

For this test I have created accounts on GitHub and BitBucket. These sites offer free hosting for software projects that use Git and Mercurial respectively.

When you start working with an existing repository you clone the entire repository to your computer. The resulting directory holds both your local repository and your working copy.

(create initial files)              (create initial files)
git add *                           hg addremove
                                     adding index.html
                                     adding images/logo.png
git commit -m "First commit"        hg commit -m "First commit"
 create index.html
 create images/logo.png
git push origin master              hg push

Here we add some files to the project. One of the files is in a different directory. Git and Mercurial track directories implicitly. By that I mean they only remember directories as file paths. This has two consequences when compared to Subversion. First you can’t add empty directories. Secondly if you commit from a sub directory you will commit the entire project.

After the files are added we commit them to the local repository and then push them to the central repository. When making the first push in Git I had to tell it which remote repository and which branch I wanted to push to.

git branch stable                   hg branch stable
git checkout stable
                                    hg commit -m "Stable branch"
git push origin stable              hg push --new-branch
(deploy code)                       (deploy code)
git checkout master                 hg update default
git branch                          hg summary

In Subversion I have been used to having a stable branch for code that I want to deploy so I can keep it separate from the latest development. I think this should still be a valid way to handle it. So we create a stable branch here and make sure we push it to the central repository as well.

One small difference here is that Mercurial automatically put us in the new branch while Git does not. In Mercurial we have to commit the new branch to our local repository. Git doesn’t see branches this way, so there is nothing to commit. The last command is just a convenient way to check which branch we are currently in as it can be easy to get lost.

(create/remove/change files)        (create/remove/change files)
git status                          hg status
 Changes not staged for commit:      M index.html
  modified: index.html               ! images\logo.png
  deleted:  images/logo.png          ? images\newlogo.png
 Untracked files:
  images/newlogo.png
                                    hg addremove
git rm images/logo.png               removing images/logo.png
git add images\newlogo.png           adding images/newlogo.png
git commit -a -m "Some changes"     hg commit -m "Some changes"
git push                            hg push

Back in the main branch (master in Git, default in Mercurial) we make some file changes that we want to commit. The status command is an easy way to see what changes are available.

Mercurial has a nice addremove command that automatically adds any untracked files and removes all missing files. In Git we have to do this manually. But here is also a very odd feature of Git, it will not automatically send changed files when we commit even if they are tracked. You have to either add them explicitly with the add command or you can give the -a argument to commit which will add all modified tracked files to the commit.

Finally we push the changes. If there are other people working on the project and you want to have their changes you use the pull command.

git checkout stable                 hg update stable
git merge master                    hg merge default
                                    hg commit -m "Merged to stable"
git push                            hg push

Finally we merge the changes to our stable branch. Again Mercurial requires us to commit the merged changes while Git has a different way of thinking.

So which one is better?

Oh look, a pony. But seriously, I wont touch that question. But I can tell you what I perceive to be different.

Mercurial

  • has better Windows support
  • has an easier learning curve

Git

  • is more widely used
  • is more flexible
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s