Recently, I started trying out git to see what the relative advantages and disadvantages of it are over Subversion, SVK, and CVS. I am not quite ready to give up the use of Subversion as the mechanism for sharing my projects with others, if only for the fact that I know more programmers familiar with it than with git (and also for the fact that my web host provides built-in support for Subversion, not git, at this time). Therefore, I’m actually using git as the front-end to access my Subversion repositories, which is quite similar to how I use SVK (and the normal model for SVK use).
The first difference I had to deal with was simply that the command-line is just a bit different. So, I had to map various ideas in Subversion/SVK/CVS into git before I could use it very successfully. Now that I’m using it comfortably, I’m certain I like it better than anything I’ve yet tried and will likely continue to use it over SVK, which was my preference up until now. On the other hand, I don’t think I’ll ever completely give up using Subversion, SVK, or CVS entirely unless and until they become obsolete tools that no one is using.
Adding Changes
Why do I like git over the alternatives? First, it helps protect me from common mistakes. For example, one thing that annoyed me at first is that you have to add any files you change to the list to be committed before committing.
% git add lib/Net/Google/PicasaWeb.pm
% git commit
That seemed a little annoying compared to how SVK lets you commit with a single “svk commit” command and select which files to commit by editting the commit message. Yet, once I got used to it, I realized that I rarely ever have to back out a mistakenly committed file. It only commits those you explicitly ask for. If you’re sure you want to commit everything, you can add whole directories or use the -a switch to commit, but the fact that you have to explicitly make these decisions rather than just committing whatever makes it difficult to make mistakes in what you commit (unless you are in hurry).
Commit by Hunk
Next, I can commit only parts of a file. This feature blew my mind. This should be a mandatory feature for any source code storage system. When I’m making a complex set of changes, but don’t make intermediate commits for whatever reason (laziness, forgot, not sure if what I’m doing in one part really serves the whole yet, etc.), I can perform an interactive patch.
% git add -p
% git commit
When running add with the -p switch, you will iterate through all the listed files (or in this case, all files changes in the repository), and be shown the diff. You can then add individual hunks from the diff to the commit or not. On the latest release of git, you can even edit the diff to pick out individual lines from the hunk to stage and leave the rest out for the moment. This is a killer feature.
Tracking Patches, Not Files
Another nice feature has to do with how git manages to deal with tracking changes. In Subversion, SVK, and CVS the most important unit to work with is the code itself. However, with git, the most important unit to work with is the diff of how the code changed from one commit to the next.
What do I mean? As an example, if I take a project and branch it to work on some complicated feature while the trunk continues to move forward. Then, I merge them when I am done, Subversion, SVK, and CVS handle the merge by diffing the branch with the trunk and then putting all the changes together in a single revision. These will use the history of the trunk and branch in various ways to help resolve problems, but they essentially treat a merge as a single diff. (SVK is a partial exception if you use the “-I” option during merges.)
With git, all the changes of the merge are copied over to the top of the trunk and then you deal with conflicts one diff at a time. This way the entire history gets pulled over from the branch onto top of the trunk, as if the work had been done from the top of the trunk in the first place. You take a little extra time to “rewrite history” this way, but it makes your patches a little more logical.
This same handling of patches works all over the place. For example if you just want to take advantage of some new features placed on the trunk, you can do something called a “rebase” rather than a “merge.” This is the same process as the merge, except all the patches remain on the same branch.
% git rebase master
You can even move the entire branch to a different base point if you want to try your branch out using features still in progress on a different branch:
% git rebase --onto bar master foo
The above command would move all the changes on branch “foo” on to branch “bar” as if these changes had been written for “bar” originally.
Under SVK or Subversion, a merge would be done by pulling in the latest trunk changes over into the branch. This adds a the trunk changes into the middle of your branch as either an individual commit (or as a set of commits with “-I” in SVK).
Work in Progress
Have you ever tried out some code changes and then realized they weren’t going to get you where you want to go? At the same time, though, there are some good ideas here that you don’t want to just throw away. In Subversion you might create a special branch to hold them, but probably not. In SVK, you might create a local branch or something to hold work in progress, but again, probably not.
In git, you can just run:
% git stash
This takes all of the changes you’ve just made and stores them quickly in a special stash. You can then see the stash and recover the latest stashed item using:
% git stash list
% git stash apply
There are a few other commands with the stash as well that are handy, but these are the ones I use most.
Those are a few of the reasons why I really like git. On the other hand, there are some aspects of SVK that are nice, such as the fact that it is very easily extended using Perl (since SVK is written in Perl and written for extensibility). I’ve been thinking about looking into adding features like these into SVK as a fun exercise since I’ve been playing with git. I sure don’t have time to do any of the other of the fun projects I do on my own time, so why not?
Cheers.

Leave a comment