views:

279

answers:

2

Some complex subversion merges are coming up in my project: big branches that have been apart for a long time. Svn gives too many conflicts - and some of them seem spurious.


Given that git is praised for a superiour merge experience, Would it be any good to use git-svn just for the benefit of making the merge more manageable?


Can you recommend other alternatives (eg. svk, hgsvn) to lessen the merge pain?

Some conflicts are easy enough to resolve (e.g java imports, whitespaces) - so I'm also wondering if there is any automated solutions for those.

A full switch to DVCS might happen in the future (some of us would love that), but not right now.

Thanks in advance.

PS: there are posts that seem to be related (eg. http://stackoverflow.com/questions/2693771/git-svn-merge-2-svn-branches) but they don't fully answer this question.

Update: see my -novice- answer after going down (and up:) this road.

+4  A: 

Trying to answer my question: using git for svn merges seems promising.

Update: it's not just promising, it's a great success. In short, Linus was right: http://www.youtube.com/watch?v=4XpnKHJAok8 @33:03.

Just completed a huge merge of 2 svn branches that have been apart for 1.5 years; 3k files were changed, got tons of conflicts in svn (~800 I think).

I found git & git-svn a life saver:

  • auto-conflict resolution: for a start, it gave a lot less conflicted files (~half I think)
  • unbelievable performance
  • excellent repo/branching model, flexible workflows: easy experimentation with various approaches, such as chunk-by-chunk(in time) merge, always doing sanity checks(compile,etc); whenever trouble hits: just backtrack. You can always just take a step back when needed.
  • usability, great tooling:
    • git-log (and the underlying git-rev-parse options), nothing can be more powerful than this. It's handy as well: -p gives you diffs in one go; in svn you get a log, then find the diff for that "revision-1:revision", or use clumsy UIs. Find when a string was added/removed into the repo, search multiple branches simultaneously
    • gitk: hugely useful for visualising branch histories, combined with great search capabilities. Haven't seen anything like this in other tools, especially not as fast as this. Nevermind it's in Tk, it's just brilliant
    • git gui: works fine even if not the sexiest - great help for the novice to discover things
    • blame: a miracle. Yes, it detects where the original segment comes from (copy&paste etc)
    • mergetool: much more pleasant experience than kicking off the big svn merge which then stops everytime (ie. every 5 minutes) it runs into a conflict, press '(p)ostpone', than manually hunt for conflicted files later. Preferred a flavour of this integrated in git gui (needed a tiny patch for that). Found integrating external diff tools better configurable than in svn.
    • pluggable merge drivers and fine grained control of them
    • rebase allowed to filter out messier parts of the svn history
  • distribution: no need to come to the office when working on this, could pause & progress step-by-step on train/plane, etc..
    • a USB drive with Unison made syncing work<->home a piece of cake
    • this wouldn't have been possible without git's crazy compression (5 years old project with 26k commits, tons of branches and binary files, trunk svn checkout: 1.9Gb => all of these in the full git repo: 1.4Gb!)

So, this really can make the difference from a nightmare to joy - especially if you enjoy learning (which does take some effort in this case - I guess like learning a motorbike after a bicycle).

Even though I can't force everyone in the company to switch immediately - I really didn't intend to actually. Again, git-svn saves us by 'dipping the toe first' approach.. But seeing colleagues' reactions the switch might happen much before anyone expected:)

I'd say- even if we forget about merges & commits, this stuff is already great as a read-only frontend for queries, visualisation, backups, etc..

Caveat:

"Do not dcommit Git merge commits to the Subversion repository. Subversion doesn’t handle merges in the same way as Git, and this will cause problems. This means you should keep your Git development history linear (i.e., no merging from other branches, just rebasing)." (last paragraph of http://learn.github.com/p/git-svn.html )

Another excellent source is the Pro Git book, section 'Switching Active Branches' basically says that the merge does work, but dcommit will only store the content of the merge, but the history will be compromised (which breaks subsequent merges), so you should drop the work branch after merge. Anyway it makes sense after all, and in practice it's easy to avoid traps here.. in svn, I found people do not usually re-merge anyway so this could only be seen as a step back if you come from git world in the first place.

Anyhow, the dcommit just worked for me. I did it onto my own svn workbranch that I kept for this only, so avoided any extra conflicts that time. However, I decided to do the final merge from this workbranch to the svn trunk in svn (after syncing up everything in git); --ignore-ancestry gave the best results there.

Update: as I found out later, the last few steps above (extra svn branch and merge--ignore-ancestry) is easily avoided by just keeping the branch you're dcomitting from linear. As Gabe says below, merge --squash just creates a simple stupid svn-friendly commit. Just when ready with huge merge(s) on the my local branch (which might take days/weeks), I would now just:

git checkout -b dcommit_helper_for_svnbranch  svnbranch
git merge --squash huge_merge_work_with_messy_nonlinear_history
git commit 'nice merge summary' # single parent, straight from the fresh svnbranch
git dcommit

I know the merge tracking won't work great from the svn-side, until we switch fully. I can't wait for that.

inger
+1 for your complete review and self-answer
Ghislain Leveque
thanks. Hope it helps others too.
inger
+1  A: 

I've just worked through this myself. A simpler method is to pass git merge the --squash option, which will perform the merge without recording a merge commit, keeping the history linear so as not to confuse git-svn.

My merge was also very large, and I had to set git config diff.renamelimit 0 so that git would correctly find all the renames.

Gabe Moothart
Cheers for that. Yes, I've been using --squash merge sometimes as well. It's also handy when you want a single combined commit rather than lots of small ones (as an alternative to 'rebase -i').
inger