28

Possible Duplicate:
I’m a Subversion geek, why should I consider or not consider Mercurial or Git or any other DVCS?

Every once in a while, you hear someone saying that distributed version control (Git, HG) is inherently better than centralized version control (like SVN) because merging is difficult and painful in SVN. The thing is, I've never had any trouble with merging in SVN, and since you only ever hear that claim being made by DVCS advocates, and not by actual SVN users, it tends to remind me of those obnoxious commercials on TV where they try to sell you something you don't need by having bumbling actors pretend that the thing you already have and works just fine is incredibly difficult to use.

And the use case that's invariably brought up is re-merging a branch, which again reminds me of those strawman product advertisements; if you know what you're doing, you shouldn't (and shouldn't ever have to) re-merge a branch in the first place. (Of course it's difficult to do when you're doing something fundamentally wrong and silly!)

So, discounting the ridiculous strawman use case, what is there in SVN merging that is inherently more difficult than merging in a DVCS system?

21
  • 6
    I am yet to work in an environment where they have months long branches being merged and they use distributed version control. The only places I have worked at that do such long lived branches used TFS/Subversion. I expect that such long lived branches would be difficult to merge with DVCSes too.
    – Oded
    Oct 26, 2012 at 19:23
  • 14
    @MasonWheeler I'm puzzled. What do you use a VCS for, then? I've seen and read that one (of the many) recommended practices is to have feature branches. Merging back to trunk is mandatory in that case. Or did I misunderstand something? (yes, the tree metaphor breaks, but it wasn't all that useful to begin with IMO)
    – Andres F.
    Oct 26, 2012 at 19:36
  • 10
    @MasonWheeler: I think you're taking the tree analogy a bit too literally. Oct 26, 2012 at 19:43
  • 6
  • 8
    @MasonWheeler how many different development environments do you have experience of, if you've never heard of merging back to trunk? Some shops have stable trunk and experimental branches, in which case cherry picking successful featurs back to stable is a regular event.
    – itsbruce
    Oct 26, 2012 at 20:01

6 Answers 6

25

It's because svn lacked the proper data structures to accurately determine the latest common ancestor of the two branches. That's not a big deal for a branch that is only merged once, but can cause a lot of erroneous merge conflicts in situations where several branches are merged multiple times.

I don't follow svn very closely, but my understanding is those particular technical issues have been fixed in recent versions. However, it wasn't fixed early enough to dispel the myth, and people who tried DVCS for the merges have stuck with it for other reasons.

0
48

if you know what you're doing, you shouldn't (and shouldn't ever have to) re-merge a branch in the first place. (Of course it's difficult to do when you're doing something fundamentally wrong and silly!)

And therein lies the source of your confusion and the whole problem in general.

You say that merging branches is "fundamentally wrong and silly". Well, that's exactly the problem: you're thinking of branches as things that shouldn't be merged. Why? Because you're an SVN user who knows that merging branches is hard. Therefore, you never do it, and you encourage others to not do it. You have been trained to avoid merging; you've developed techniques that you use to avoid merging.

I'm a Mercurial user. Even on my own projects, where I'm the only developer, I merge branches all the time. I have a release branch, which I put a fix into. Well, I merge that back into the main-line so that the fix goes there.

If I were using SVN, I would adopt a completely different structure of the codebase. Why? Because SVN makes merges hard, and therefore you develop idioms and techniques to avoid doing complex merges.

DVCS's make complex merges easy because they are the default state. Everything is a branch, more or less, in a DVCS. So the entire structure of them is built from the ground up to make merging easier. This allows you to develop a workflow that uses merging on a daily basis, rather than the SVN workflow where you never use merging.

The simple fact is this: you should approach a DVCS in a different way than SVN. You should use the proper idioms for these very different kinds of version control systems. In SVN, you adopt idioms that don't involve merging because merges are hard. In DVCS's, you adopt idioms that frequently use merges because they're no big deal.

Right tool for the right job.

The thing is, the merge-focused workflow is a lot nicer and easier to use than the SVN-style workflow where you don't merge things. It's easier to see when something from the release branch was brought into the dev branch. It's easier to see the various interplay between branches. It's easy to create test branches for things, then clip them off if the test doesn't work. And so on.

Really, Joel explains this a lot better than I can. You should have a good read of that.

15
  • 15
    @Mason: How is that not training? You were trained to use SVN in an SVN style. And the SVN style is to not use merging. Thus, you were trained to not use or even consider merging things. That's why it never occurred to you; because you used a system that makes it difficult. Oct 26, 2012 at 20:53
  • 5
    There's a big difference between "not trained to" and "trained not to." Oct 26, 2012 at 20:53
  • 8
    @MasonWheeler: No, there isn't. If you are not properly taught how to do something, then you are implicitly trained to not do it. It isn't in your repertoire of idioms you can employ to solve a problem. Therefore, you cannot use it to solve problems. The effect is no different from being told not to merge, because even if you wanted to, you don't know how. The way you offhandedly dismiss a good argument as "the same tired old ground" is evidence of this. You don't think of merging as a tool; you think of it as the exception or something unusual. Something to be questioned rather than used. Oct 26, 2012 at 20:56
  • 10
    @MasonWheeler: Who are you to decide "they're doing it wrong"? You don't use DVCSs, so you have no experience with the DVCS workflow. You have no idea whether it is helpful to programmers or not, as you have no experience with it. So what authority do you have to say that it's "wrong" just because SVN doesn't allow it? It's like saying that classes, virtual functions, and templates are wrong because C doesn't have them. Oct 26, 2012 at 21:13
  • 3
    @MasonWheeler: like this? :P. SVN branching and merging does the same thing - the metaphor is already broken. I don't really see how something like this is that hard to understand, especially if it includes some sensible commit comments..
    – naught101
    Jan 6, 2015 at 1:49
23

There is nothing too difficult about SVN merging... anymore... if you follow the right philosophy

What I see in most other answers seems to come from people who haven't used SVN in a while. As someone accurately mentions: "it wasn't fixed early enough to dispel the myth".

From my current experience of using SVN 1.6 to 1.8 on a legacy project I inherited recently, SVN has gone a long way towards making merging a much easier thing. It is not foolproof, though, and I think it does not easily suffer users deviating from the intended use.

While I knew SVN quite well and had also tried Mercurial for personal projects in the meantime, I had never done a lot of branching in SVN prior to this project. There was quite a bit of trial and error and I got a lot of unexpected merge conflicts when I started.

Ultimately, though, I realized that everytime I got one (or some other issue), it was because I hadn't done things properly (aka "the SVN way" -- arguably, the proper version control way). I believe this is where the difficulty lies: you cannot do whatever you want in an unorganized way and expect SVN to work perfectly, especially with merges. Merges require rigorous discipline from the user(s) before they show their true power.

Here are things I've noticed are strong recommendations, if not requirements, for a clean use of merges:

  • Use a recent version of SVN (1.6 and up in my opinion). More and more automation and checks are done for you.
  • Use the default "trunk, branches, tags" structure and apply its philosophy (don't commit to tags). SVN won't check anything for you. If you use a tag as a branch (that's the state I found that project repository in), it can still work, but you need to be consistent.
  • Know what branches are and when to create them. Same with tags.
  • Keep side branches up-to-date with their source branch (usually trunk, but you can branch out from any branch technically). This is mandatory IF you want SVN to do auto-merges. SVN 1.8 actually prevents you from auto-merging if things are not up-to-date, and also if you have pending modifications in your working copy (this behavior seems to have disappeared again in 1.8.5).
  • Do "proper" commits. They should only contain modifications on a very specific concept. As much as possible, they should contain a small amount of change. You do not want to have a single commit contain modifications about two independant bugs for example. If you have already fixed both and they're in the same file, you should store away the changes of one bug so you can commit just the changes of the other first, then commit the second set of changes. Note that TortoiseSVN allows this easily through "Restore after commit".
    • Doing so makes it possible to revert a specific independant set of changes AND makes it possible to only merge such a set into another branch. Yes, SVN allows you to merge cherry-picked revisions.
  • If you ever use sub-branches (branching off trunk, then branching off that new branch), respect the hierarchy. If you update the sub-branch with the trunk or vice versa, you're in for some pain. Merges should be cascaded down or up the hierarchy.
    • After a few months of experimenting, I can vouch that this might be the most important part. Tried creating two sub-branches from the same trunk and then merging bits between the sub-branches, or sometimes between sub-sub-branches from either side. This can trip up SVN (or the user). It can work OK if you're merging specific revisions. Auto-merge may have trouble with it.
    • I have had trouble specifically when synchronizing sub-branch A with trunk, and then trying to merge something from sub-branch A into sub-branch B. SVN seems to think the "synchronize from trunk" revision should legitimately be merged into sub-branch B and this leads to a mass of conflicts.
  • As much as possible, merge from the root of the branch. Otherwise, SVN will only keep track of the merges done for the sub-folder and when you do try to auto-merge from the root, you may get warnings about missing unmerged revisions. It's fixable by simply merging these from the root, but best avoid the confusion.
  • Be careful which branch you commit to. If you use Switch to have your working copy point to various branches through time, be sure where you're committing to.
    • It's especially bad if you really didn't want the change in that branch. I'm still not clear on that one, but depending on how you get rid of it / transfer it into the right branch (reverting, merging), you can get something messy. It's fixable, but you'll either have to merge revision by revision to avoid or immediately solve potential conflicts, or you'll have to fix a possibly more complex conflict after the auto-merge.
  • Do not keep branches untouched for too long. Actually, it's not a matter of time but of how many revisions were committed to the branch and the trunk and how much changed in these. Merges between two branches, 3-way merges, always get compared to most recent common revision between the branches. The more changes in-between, the more change the automatic merging will fail. This is, of course, much worse if you changed the structure of your code in the meantime (moved or renamed files).

If you don't follow the above, you're quite likely to get conflicts. They're always solvable, but not terribly fun to spend time on.

Oh, one more thing about merging where, from all I've read and tried, SVN really sucks: deleted/moved/renamed files/folders. Apparently, SVN still cannot deal with a file being renamed, deleted or moved in one branch, and its original version modified in another branch... and then merging these together. It just won't know where the file went in one way, and will "forget" the changes in the other way. One change is obviously unsolvable (you either delete or change the file, can't do both), but applying changes to moved/renamed files should work and it doesn't. Hopefully this gets fixed soon.

So, all in all, is SVN merging easy? I guess not. Not in a carefree way, for sure. Is it bad? I don't think so. It only spits back in your face when you use it the wrong way and don't think enough about what you're doing.

Based on this, I can see why people might prefer Mercurial (for example) as it's a little more lenient about these things from my experience and had everything automated from the get-go (at least from the early versions I started with). SVN has caught up quite a bit, though, so it's not worthy of so much bashing anymore.

4
  • Tree conflicts - yes, SVN has difficulty with these, though TBH so do every other SCM. Git has some heuristics to try and figure out if files that have been renamed or moved are the same, but it doesn't (cannot!) always get it right. I think SVN should put some effort into making resolving these conflicts easier to understand.
    – gbjbaanb
    Jul 20, 2014 at 18:22
  • @gbjbaanb: It does offer "Repair Move" as Mercurial does, though it doesn't offer heuristics. You need to tell it which Deleted and Added files are, in fact, the same. Definitely room for improvement.
    – leokhorn
    Jul 21, 2014 at 8:22
  • All of this sounds great when you are the only person working on the project ... But if you have a good sized team and they are all using it the "SVN way" (which nobody seems to agree on exactly what that is) merges are still a PITA. The fact is svn doesn't really support the branching workflow that well. The "SVN way" would be to not even create branches and use a waterfall SDLC. All that being said, I've had issues with Git merges in the past on large projects with several people people working on it. But, they seemed to still be a lot less painful.
    – ryoung
    Aug 27, 2015 at 14:43
  • My experience is that if you are working with people who don't care about how the version control system works, SVN is way easier to use on a day to day basis. I've worked only on a few DVCS teams but invariably some substantial number of the team do not have good revision control behavior and it pollutes the repository for everyone. In Subversion, the untrained generally stay away from branches so they get the "experts" to do it for them and they are managed appropriately. Granted, this experience is mine alone and I'd prefer to only work with programmers who knew how their tools worked... Jun 13, 2018 at 1:55
5

The internal data models are fundamentally different.

Fundamentally, in SVN, when you look at the history of a branch, you only see what has happened in that branch. So when you merge from branch B to branch A, the history of branch A will contain one large commit containing all the changes made explicitly to B since it was branched.

In the first versions of SVN, if you had to merge branch B into branch A once more, you had to manually specify which revision range of branch B you wanted to merge in order to avoid merging the same revisions twice. The clever developer would of course use a commit message like 'Merged in B:1234'.

SVN 1.5 "fixed" this. But it did not change how merges are applied fundamentally. It merely added some extra metadata to branch A, letting SVN know that revision 1234 had been merged in, allowing SVN to automatically choose the correct revision range.

But this solution is basically a workaround for a data model that fundamentally doesn't support track what has been merged.

Merging two branches is a relatively simple example. But imaging this more complex scenario

  1. Create branch A from trunk, and make a few commits here
  2. Create branch B from A and make a few commits here
  3. Make a few commits in trunk and A
  4. Merge B into trunk
  5. Merge A into B
  6. Merge A into trunk
  7. Merge B into trunk (this shouldn't actually do anything)

Handling this correctly using the metadata model becomes extremely complex (I don't know if SVN does indeed handle this scenario correctly, and I don't feel inclined to test it out).

Handling this scenario in git is extremely simple.

In git, every time you commit, the internal object representing that commit contains a reference to the previous head. When you merge in a branch, the commit contains references to the previous head of all the branches being merged (you can merge more than one branch at a time in git)

Therefore, when you examine the history of a single commit in git, you can see all history, you can see when it was branched, when it was merged, and you can see the history of both branches between the branching and the merging.

Thus when merging in a branch that has been partly merged, it is extremely simple to determine what has been merged already, and what has not.

I have no experience with Mercurial, but I suspect that its internal workings are similar to git.

So fundamentally, for SVN, it was a design goal to make branching cheap. But in git, it was a design goal to make merging cheap.

Lastly, last time I used SVN, it was not able to handle merges, where a file was renamed in one branch, and modified in another.

1

I've done a fair bit of SVN merging -- including having long running development and release branches. By and large I survived. Merging is always tricky, but with DCVS the downside is not horribly bad -- everything is local so just update to a known good revision and keep going. Whereas with SVN alot happened on the server side so recovery was ugly -- usually it involved wiping out the local copy then checking out a new clean branch to try it again. Wasn't bad in my case -- a gigabit connection to the SVN box helps. But we had some contractors who had lots of trouble with this as they were on slow connections so anything took forever, including merges.

1
  • extrapolating on the slow connection thing, working from an offsite remote server makes for lousy dropped connection errors too when making large updates >< Not fun at all.
    – jxramos
    Nov 17, 2015 at 22:51
-1

Yes, I do that too. I currently have 12 VMs for different versions (branches) of the project I'm part of at work. When I have to fix a bug in an older version, I fix the bug, then merge that commit into the branches for newer versions. But that's now re-merging an entire branch, which is what I'm talking about here.

Here lies one of the very nice things about git. It's not inherit about DVCS, it's just something git excels at. You can merge specific revisions from any branch into another branch. It basically just takes the diff and applies it to the other branch, but does tracking and is much more automatic.

So, if you have branch 2.0 and branch 3.0 and discover a bug in 2.0, you can then fix it in 2.0 and take the set of revisions which resolve it and merge only those revisions into the 3.0 branch. I don't believe SVN has any way to do this other than manually taking the diffs for each revision and applying them

Of course, the auto-merge algorithm also appears to work a lot smoother and git was built from the ground up on the "make a branch for all the things" model, so branching is just really smooth and easy in it. It just seems natural to branch often with how lightweight it's branches are

6
  • Also, I'd imagine that mercurial has similar functionality
    – Earlz
    Oct 26, 2012 at 20:40
  • 2
    Actually, you can do the exact same thing in SVN. I do it all the time. The SVN Merge command can pull a revision (or range of revisions) from a different branch and apply it to your working copy, and then you commit it. Oct 26, 2012 at 20:40
  • 2
    @MasonWheeler Keep in mind that a lot of the anti-svn sentiment was directed to versions prior to 1.5 (when svn got merge tracking). And of course a lot of it is just pointless fanboyism...
    – yannis
    Oct 26, 2012 at 20:42
  • 3
    @MasonWheeler see also stackoverflow.com/a/4215199/69742 That post boils down to DVCS keeps track of change-sets not versions. Change-sets are inherently easy to take and merge... versions not so much because they require context
    – Earlz
    Oct 26, 2012 at 20:44
  • @MasonWheeler oh and this one: stackoverflow.com/questions/2471606/…
    – Earlz
    Oct 26, 2012 at 20:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.