Confessions of a Git Skeptic

A year ago, I was happily using Subversion for my version control, and reading about Git. It sounded intriguing, and there were lots of articles about the life-changing enlightenment of switching to Git. Frictionless branching and merging? A whole new elegant model of file management? Plus I get to think about directed acyclic graphs? Cool.

For the last few months, I’ve been using Git pretty much every day. But sadly, I’m still waiting for the epiphany. Here’s how I reckon up the pros and cons. Maybe it will help someone else with this transition. (Please note that I don’t have the pleasure of knowing other nifty new distributed version control systems like Bazaar and Mercurial.)

Let’s start with the good stuff.

Git really is faster. I’m still startled sometimes to realize that my command already finished running. In particular, something like switching between branches is very smooth. So far, so groovy.

Oh, and Git manages its internal files better. It puts the whole version-control business in a single .git directory, rather than spreading it out in .svn directories all over the place. I hate those .svn directories: they give me false positives when I’m searching my files, and it’s pretty easy to mix two incompatible working copies accidentally, throwing Subversion into a subtle confusion that requires checking out the whole project again. Well done Git!

Here’s what bugs me, though: Git complicates my life without giving me much in return. Here are the bad points.

Git adds extra steps to the flow of content between your local files and the remote repository. This is Exhibit A for me, as it annoys me every day. In Subversion, you have the local working copy, and the remote repository. That’s two states of the code, with clear and distinct purposes. In Git, you have three more steps in between those two: the staging area, the local repository, and the remote branch. That’s five states of the code, all of which are different, and all of which you need to understand.

Let’s see how this plays out in the daily workflow. In Subversion, you use “svn update” to move the code downstream, and “svn commit” to move it upstream. In Git, the downstream commands are “git fetch” (to move code to the remote branch) and “git merge” (to the local repository, I think). The upstream commands are “git add” (to the staging area), “git commit” (to the local repository), and “git push” (to the remote repository).

That’s five commands instead of two. You can use “pull” to mean “fetch and merge”, but some authorities will advise you not to. You can also use “commit -a” to avoid the “add”, but you still have to be aware of it.

The staging area is also known as the “index” and the “cached” files. Yes, you will find all three of these terms used in documentation and tutorials, and they all mean the same thing. The staging area allows you to commit only some of your work, rather than all of it. This is something I am occasionally tempted to do, but not something I want to worry about all the time.

The remote branch (for example, “origin/mybranch”) is a strange beast. It’s a local pointer to the remote repository, and it may or may not be up to date. It’s involved in the downstream but not the upstream flow, for some reason.

If you want to clean up an unused branch, that’s fine, but remember that you have to do it in both the local and remote repositories, with “git branch -d mybranch” and the amazing “git push origin :mybranch”, respectively. (To be fair, that second command seems to have embarrassed even the Git developers, so they provided the somewhat clearer “git push origin –delete mybranch”.)

In my current project, we maintain extra repositories on a staging server for deployment, which compounds the extra-steps problem. I find myself the most Git-savvy person on the team, so it’s my job to explain the Git process to my colleagues, awkwardly: “Yes, I know it’s a pain, but that’s how it works.” We keep things under control by maintaining detailed sample scripts for everyone to refer to. We would do the same if we were in Subversion; it’s just that the scripts would be shorter.

Git commit names are annoyingly opaque. This is the kind of thing you don’t miss till it’s gone, but consider the Subversion revision numbers 546, 547, and 987, and how brief and informative they are. In Git, these would probably be the commits 7b558b6, e329317, and 0cccacb. (Or maybe you’re unlucky and that last one is not unique, so you have to say 0cccacb1 instead. Yes, it’s unlikely, but there are no guarantees.)

Git forces me to learn obscure things that don’t seem to relate to my work. For example, some repositories are “bare repositories”; I don’t remember what that means, but I needed to know it briefly once. Sometimes the repository is in a state called “detached HEAD”, which means (roughly speaking) that it’s not at the current state of one of your branches, but at an older state instead. There’s an advanced feature called “reflogs” which I might need someday to retrieve data in my repository that I lost. (Isn’t that something that should be standard, not obscure, in a version control system?)

To be fair, Subversion made me learn what “peg revisions” are, and what “svn:mergeinfo” properties are. I guess those just make more sense to me than the Git examples above.

Finally, there are a couple of points that are neither good nor bad, but neutral.

Git allows the topic-branch development style, where you maintain one short-lived branch for every task you work on. Like many people, I learned about this style from distributed version control. I love it. It’s an excellent way to switch between tasks, and maps well to the way I actually think about the state of the project.

But you don’t need Git to do this! Subversion has “svn switch”. It does have an annoying problem that if you specify the wrong URL to switch to, it will trash your local copy rather badly. However, Subversion seems to have fixed that problem in version 1.7. (It also fixed the multiple .svn directories problem I complained about above.)

Git allows cleaning up your history by rearranging the commits in your local repository before they go out to the remote repository. See, for example, the “rebase” command. This is kind of neat, but I’ve never found a compelling reason to do it. I’m happy to have the remote repository record what actually happened.

I’m still using Git. I want to give it a fair trial. (After all, I remember the transition from CVS to Subversion. Do I want to go back to CVS? No, I do not.) And here’s what I think: Git’s an interesting experiment. Perhaps my eureka moment is still to come. Till then, if I have a choice, I’ll stick with Subversion.

14 Comments

Git gives you power and flexibility un matched in other version control systems imo. Some of my favourites:

git add -p – Patch mode for adding code to the stage area. It means you pick lines of code across multiple files that are within context of a commit. So say I make several changes to a file, some un related, using git add -p I can pick the code that I want and leave the rest for another commit, giving you a more organised commit history.

git cherry-pick – Say someones just push something on another branch that you need for the branch your working on, you can do that, just checkout the other persons branch, pull it, check out your branch, git cherry-pick 2799c53ebb64233e209de36325411b6402a6d5eb. You won’y get conflicts when the 2 branches eventually merge.

git stash – Someone on your dev team needs help on another branch, or even the same branch but you have uncommitted changes thats not ready yet. Git stash them, check out the other branch do some work etc, when your done come back to your original work, git stash apply and your work from before is back.

Theres loads more. I come form an SVN background and I really hate going back to it now for legacy projects. Yeah gits a bit complicated but stick with it, it will click 🙂

This is an excellent summary of the benefits, and yet many shortcomings, I’ve seen with Git too. I use and prefer Git these days instead SVN. But it is definitely not as straightforward as SVN and it comes with a host of baggage and complexities (many of which seem unnecessary).

It’s interesting to observe how fast many in the software dev community have glossed over these shortcomings. I think the benefits do outweigh the cons, but not to the extent one might be led to believe.

Rollerboy
on February 20, 2013 at 10:30 am

When was SVN 1.7 released? Git has existed for 8 years now, and you might thank Git for the competition that has pressured SVN to improve upon these longstanding issues!

Who Cares
on February 20, 2013 at 10:50 am

well, GIT is not SVN. Surprise!

Seriously, why do you expect GIT would do things the same way SVN does? It’s DISTRIBUTED VCS so it cannot for example handle sequential revisions numbers?

GIT is better as SVN. But many people don’t get it and say Oh, svn is so simple…

By definition, all of you points are valid since they are in the context of what pleases and bothers you. The problem with a post like this though is that readers may conflate your view with reality. This is not a critisim of your post, more a critisim of the internet-reader problem. I’ve use git for quite some time and frankly can’t live without it. Regarding the number of steps, I’ve simply created scripts as needed that reduce things to a minimal level in the development process. I have to admit I’ve not yet tackled the problem of remote depositories as yet and after 30+ years of being a lone wolf coder, it is unlikely I’ll ever have to solve the problems of more than one developer 🙂 As a slight case of solidarity, I’m am not at all happy with ‘version’ numbers! They aren’t comprehensible and are pretty much pointless as far as I’m concerned. What I do is keep a text file called (wait for it…) ‘version.txt’. This is a file containing the usual text “0.0.N” where N is initially 0 and then I use a perl script to increment the version with overflows at 100 for each number. Admittedly a bit of a ‘sledge-hammer’ solution, but as they say, “It works for me!” Good cogent column—thanks!

Generally I would say that there is almost nothing better about SVN as a version control system, but I would say that it’s limited set of features map more closely to peoples mental models and thus are much more approachable / easier to pick up.

Git has some weird unintuitive Linus Torvolds-y things that stump people for a long time until they fully understand them. This is why there have been efforts to “humanize” some the commonly used and complicated git operations. You can use something like http://www.git-legit.org/ as well as setup your own alias to alleviate this.

Just curious why no one has mentioned Perforce yet? It has a nice cross-platform GUI, and can easily version all file types including asset files and binaries. Having used all three VC tools at one point or another, I find it the easiest to use by far.

Troy J. Farrell
on February 25, 2013 at 6:23 am

Perforce works well with you’re working with non-programmers. As a programmer, I find that Perforce is the worst of the {git, Subversion, Perforce} set. You have to checkout files before they are marked read-write on the filesystem. You have to get your clientspec just right and setup a new one on each computer that uses Perforce. Perforce is good at not losing data, but it really slows down my work.

johnwun
on February 25, 2013 at 9:33 am

Thanks for the detailed response Troy. I agree with the pain of setup, but I don’t feel inconvenienced using it. Our development team has been using p4 for the last 2 years, and with eclipse/intelleJ integration, checkouts/check-ins are extremely fluid. When we were using svn some checking got mugged, and it was a pain to figure out what happened, also, I wasn’t a big fan of the ‘.svn’ folders everywhere. I’m still undecided about git, but after using p4, I’d never go back to svn.

Br.Bill
on September 16, 2015 at 2:05 am

You don’t have to check out in Perforce if you don’t want to. That is a client [workspace] option, configurable by the user. You can choose to do it the way that SVN and git do. But, like git and svn, with today’s dev tools you’re likely to add files to your repository that you didn’t want to. Unless your .git-ignore or .p4ignore files are 100% perfect. They’re usually not.

Joe McTee
on February 21, 2013 at 11:10 am

The graphic at the beginning of your article is a representation of one possible workflow using git, namely Gitflow. I know it has its proponents, but most folks I know who are comfortable with git don’t se and really don’t like Gitflow. Probably worth mentioning this to avoid confusion.

For open source projects (such as Linux OS), git makes a huge difference in workflow, I think that has driven it’s popularity. Perhaps you’re not working on enough github projects to see the benefit for yourself.

The “feature branch” concept is nice in theory, but for a team that is well coordinated (unlike some of those open source projects) it’s probably not better than the subversion way; it actually discourages refactoring and other sweeping changes. See http://martinfowler.com/bliki/FeatureBranch.html for a Martin Fowler’s discussion of this.

Even for a smaller team, however, the speed boost alone is well worth climbing the learning curve.

There are decent GUI wrappers for Git and IDE integrations that take most of the pain away. I only occasionally use git from the command line, now. These tools often make it easy to combine a few steps into one.

Art+Logic has been designing and developing innovative custom software since 1991. We have built software for over 900 clients from a diverse set of industries including education, aerospace, music technology, consumer electronics, entertainment, financial services, and more. Coding the “impossible.”®