So why git-svn? Well, we have historically been standardizing on CVS and Subversion at my work place, and all of our code is versioned by one of these systems. I could mention many things that I dislike about these two SCMs, but their Eclipse integration is pretty good, and that has been politically decided to be a big plus. Therefore, all code I produce at work must be put in either CVS or Subversion, and Git is not under consideration until it can be shown that the EGit Eclipse plug-in has accrued an acceptable amount of awesome. This is why I decided to put my faith in git-svn two months back.
As you might have guessed from the title, things aren't all rosy. It's not that git-svn doesn't work, it's the way it works that is bothering me. Git allows you to manipulate the history of your repository, and when you do a merge in Git, the commits from each branch will be chronically interspersed in between each other. This model does not map very well to Subversion. If I merge a branch into trunk in subversion, I am in essence making one big fat commit to trunk that goes on top of all of the existing commits, and contains all of the changes from the branch. There is no history rewriting because the history is lost by flattening all of these commits into one.
Therefor, to shoe-horn itself into this model, git-svn will use rebasing instead of merging. When you rebase a branch A unto another branch B in git, you are taking all commits from A that are not already in B, and reapply them, in order, to the HEAD of B. This makes it look like these commits where written and committed after all other commits in B.
This is a clever trick but it comes at a pretty high cost. A commit that is retrofitted to have a different past, is no longer the same commit. So what happens when you make some changes in B that you back in A? With ordinary merging in Git, this problem is trivial - you simply merge B back into A. However, because of the rebasing, A and B now contain two sets of commits that are essentially the same changes, but with different past and therefore different commits. This means that merging breaks down. If its just one or two commits we're talking about, then we can cherry-pick. But if we are talking about a larger set of changes, then we quickly find ourselves reaching for the
Rebasing is a powerful tool that allows us to rewrite history. However, if we use it too much, we can quickly rewrite ourselves hairy mess of unmergeable branches. Consider this: just as we can get merge failures when two commits are incompatible, we can likewise get rebase failures. But because rebasing is reapplying all distinct commits in order, a rebase failure will affect all subsequent commits waiting in line of the rebasing process. A merge failure is resolved once for a merge, but if you are rebasing 10 commits unto a branch and the third commit fails, then that failure could potentially propagate to the seven other commits, if they depend on the changes in a failing earlier commit.
What are the consequences of this? Because git-svn does a rebase on every git-svn dcommit and git-svn rebase, thus (more or less) rewriting history, I am pretty much left with a git repository where cheap local branches and merging is somewhere between troublesome and non-functioning.
That's a pretty steep cost, in my humble opinion. But I still use it. Yes, despite these dragons and drawbacks, I still use git-svn as my primary Subversion client. I still like my ability to freely mold and modify unpushed history, I still like my git-bisect and I still like colored console output.
I have experienced these pitfalls on my own repositories and I have learned to avoid them. But if you think that you can reap the benefits of Git while keeping ye olden Subversion around, then you're wrong. With git-svn, you are voluntarily pulling a SVN branded straight jacket over your Git repository. To truly get the most out of Git, you absolutely have to sync with a real remote Git repository.