svngitversion-controlmercurial

For home projects, can Mercurial or Git (or other DVCS) provide more advantages over Subversion?


Which free source control system is most preferable with reason for home projects and documents?

I am thinking to use Subversion (as I am familiar with it).

Characteristic of home project:

  1. Most likely single person will be committing changes. (May be one day (not now), it is possible that I share a project with my friend who is in other city)

  2. I would like to store other documents (non-programming files)

Is Mercurial or GIT (distributed version control system) can give me any more advantage over to subversion in Home Projects?


Solution

  • Take a look at part about version control for single developer in my answer to "Difference between GIT and CVS" question here on StackOverflow. Some of those issues do still apply also to Subversion versus Git (or other distributed VCS: Mercurial, Bazaar, or less known: Monotone, Darcs), even if Subversion is an improvement over CVS.

    DISCLAIMER: I use Git (so I am biased), and know Subversion only from the documentation (and other resources), never having used it myself. I might then be mistaken about Subversion capabilities.

    Below there are list of differences between Git over Subversion for a single developer, on single machine (single account):

    In Subversion (in any centralized version control system) you need to set up central repository (unless you did that earlier) using svnadmin create (well, you need to do that only once). Then you have to import files into Subversion using svn import (or svn add)... But note that after the import is finished, the original tree is not converted into a working copy. To start working, you still need to "svn checkout" a fresh working copy of the tree.

    Subversion stores repository in separate area you have to put for that purpose, and stores repository metadata (e.g. where central repository is, identity used to contact central repository, and I think also properties like svn:ignore) are stored in .svn directory in each directory of your project. (Note that Subversion stores pristine copy of your checkout, to have fast svn status and svn diff)

    In Git each version of a project (each commit) has its unique name given by a SHA-1 id with 40 hexadecimal digits; usually first 7-8 characters are enough to identify a commit (you can't use simple numbering scheme for versions in distributed version control system -- that requires central numbering authority). But Git offers also other kinds of revision specifiers, for example HEAD^ means parent of a current commit, master~5 means revision 5 ancestors back (in straight first-parent line) from top commit on a 'master' branch, v1.6.3-rc2 might mean revision tagged v1.6.3-rc2.

    See also Many different kinds of revision specifiers blog post by Elijah Newren.

    Branches have an unusual implementation in Subversion; they are handled by a namespacing convention: a branch is the combination of revisions within the global repository that exist within a certain namespace. Creating a new branch is done by copying an existing set of files from one namespace to another, recorded as a revision itself. Subversion made it easy to create new branch... but up until version 1.5 you had to use extra tools such as SVK or svnmerge extensions to be able to merge easily. Subversion 1.5 introduced svn:mergeinfo property, but even then, merging is slightly more complicated than in Git; also, you need to use extra options to show and make use of merge tracking information in tools such as svn log and svn blame. I have heard that it doesn't work correctly in more complicated situations (criss-cross merge), and cannot deal currently with renames (there is even chance of silent corruption in such case). See also (for example) this post on git mailing list by Dmitry Potapov, explaining intended use case for svn:mergeinfo and its (current) limitations.

    In Subversion, tags use the same path_info-like namespace convention as branches (recommended convention is svnroot/project/tags/tagname), and are not protected against changing. They are made using "svn copy". They can have comment associated with [the commit creating a tag].

    Both Git and Subversion do keyword expansion only on request.

    Subversion uses global-ignores runtime configuration option (which generally apply to particular computer or by a particular user of a computer), and svn:ignore property on SVN-versioned directories. However unlike the global-ignores option (and in .gitignore), the patterns found in the svn:ignore property apply only to the directory on which that property is set, and not to any of its subdirectories. Also, Subversion does not recognize the use of the ! prefix to pattern as exception mechanism.

    Subversion allows only to modify commit message after the fact, by changing appropriate property.

    On the other hand, Subversion because exists longer, has perhaps wider set of third party tools, and Subversion support in tools, than Git, or at least more mature, especially on MS Windows.


    And there is another issue, which might be quite important later:

    I guess it is more complicated with Subversion, if you don't start at software hosting site with Subversion support (like SourceForge) from the beginning, unless you don't want to preserve existing revision history. On the other hand, for example, Google Code suggest to use svnsync tool (part of the standard Subversion distribution), as explained in Google Products‎ > ‎Project Hosting (the Data Liberation Front) article.


    Also, take a look at http://whygitisbetterthanx.com/ site.