Home > software > Why I prefer git over SVN

Why I prefer git over SVN

September 19th, 2007

Since getting more famialiar with git (the version control system) over last year, I have started increasingly favoring git for my own projects (over, or side-by-side with Subversion (SVN)). This post explains some reasons why.

The first time I tried out git was probably somewhere towards end of 2006. It was mostly out of curiosity, but I also needed something that I could do some local version control with. The reason was that I wanted to hack some customizations on release tarballs, while still maintaining a version history and annotation for my own changes. At some point I even used diff and patch for this, and needless to say it was quite cumbersome.

So, git fit nicely in the picture. I even used it over SSH to clone the project to another computer and learned to use push/pull to send the changes back to my main workstation. However, I didn’t really discover all the benefits and continued to use Subversion for most of my projects.

Around march of 2007, I realized that Subversion just did not cover my changed needs. The problem was that I needed to work offline with a laptop and well, with a centralized version control system that does not really work at all: all the work you do offline needs to be committed in one huge chunk when online again.

git-svn

I started looking at alternatives, and discovered git-svn. It allows you to checkout a Subversion repository with full history, work locally with it like you would with a normal git project (apart from some limits), and then commit those changes back to Subversion. Perfect for my needs.

Upsides:

  • The “backend” is still Subversion, and no special tricks need to be done. In fact, no one knows whether you use git-svn with SVN repositories or not.
  • You can make local (fast!) commits as much as you want, and then push them to the SVN repository at once.
  • Full history available locally.
  • Most checkouts (with FULL history) actually take less space than a SVN checkout with only latest revision.

Working with git-svn allowed a smooth learning curve to get familiar with git, and I started using pure git repositories for some new projects. Some problems with git-svn led me into thinking that using pure git is a better choice for my projects. For example:

  • When working offline for long and then committing all changes to SVN, metadata such as date of change is lost (all of the SVN commits will bear current date).
  • SVN only supports linear history and has no merge tracking, so you can’t really make use of some of the best git features when using git-svn.
  • Branching is tricky.

git – evaluation

  • Deciding factors
    • Fast. This does affect how you work. Fast committing makes it convenient to break changes into feature/fix commits, which is a good thing. Compared of SVN where you subconsciously avoid committing because it’s so damn slow (and about every other action is slow as well because they work over network).
    • Proper branching, merging and merge tracking. This totally changed how I think of branches. I hardly ever used them with SVN, but I use them all the time with git.
    • Can be cloned from a normal HTTP server. Not even git needs to be installed (if you upload with rsync or whatever)!
    • Creating local changes and branches is indefinitely easier. So is submitting and applying patches. Git has tools to automatically format commits to be sent with e-mail. Author and committer can be different.
  • Interesting points
    • Small size. At least for projects with reasonably small history (few thousand revisions) the git checkout (with full history) is almost always smaller than the svn checkout of HEAD. This sounds really insane at first, but it’s true.
      • Example: A certain project here has a .git directory weighting 144 MiB. The checkout in git is 1.1 GiB, so SVN checkout would be more than 2 GiB. And that’s one revision, compared to the 7140 revisions the git repository is holding, while still taking 777 MiB less space.
    • Disconnected branches / multiple initial commits. This goes in the general category of “git being flexible”. You can have a git repository with two branches that share no history. I use this for having the actual source code and the project webpage in the same repository.
    • You can merge development histories of multiple projects into one git project. Try this, or anything that messes with history in SVN. Can’t? That’s why I like git.
    • History can be rewritten quite freely.
      • Simple “last commit” fixing with git-commit –amend.
      • Rebasing.
      • Discarding of history or particular commits.
    • No more twiddling with repository permissions. A developer can simply clone a repository, work on a local branch, and finally ask the maintainer to “pull branch xxx from here”.
  • Downsides
    • No partial checkouts. SVN repositories can be huge, and users can only check out a certain subdirectory.
    • No feature similar to svn:externals (this is being worked on).
    • Shallow clones (checkouts with incomplete history) are very limited.

Conclusions

git and SVN are very different version control systems (as different as distributed and central version control models are from each other), and both have their places. git-svn is a good tool that brings some benefits of distributed control systems to projects using SVN.

I personally believe that distributed version control systems will continue gaining wider adoption in the free software world, and possibly work their way into corporations as well. Distributed version control systems also seem more natural choice for free software projects. At least following the development should prove to be interesting! :-)

Links

software ,

  1. February 25th, 2009 at 12:08 | #1

    “You can merge development histories of multiple projects into one git project”

    could you share more info on how you did it

  2. hoxu
    February 27th, 2009 at 17:10 | #2

    @Senthil Nayagam

    I don’t remember too well what I meant with that, but most likely something like this:


    $ mkdir a; cd a; git init
    # import history of project A
    $ cd ..
    $ mkdir b; cd b; git init
    # import history of project B
    $ cd ../a; git fetch ../b/ master:b # fetch 'master' branch of 'b' to 'b' branch
    $ git merge b # merge 'b' with 'a'
    $ git log # shows history of both projects

  1. No trackbacks yet.