
Frank Birbacher <bloodymir.crap@gmx.net> writes:
Hi!
Thanks very much for your feedback! Both of you.
Am 28.03.12 22:49, schrieb Martin Geisler:
So, it's very similar for this example.
Yes, so to me there is no significant difference in the commands that create and merge branches.
Agreed, the differences are just syntax! Btw, I consider SVN a super centralized version control system, so this is not surprising.
In the commands that is! You provided an example where a rename leads to a conflict in svn, but not in hg or git. That's a drawback on svn of course. On the other hand it is a reported bug and likely to be fixed (I wonder why this hasn't been fixed already, v1.5 has already been a while on stage.)
I know Boost is C++ and not, say, Java, so maybe you don't run into this very often? When I talk to people using Java it sounds like they're moving files around all day :) So it's really important for them that they can merge a branch back to trunk even when files have been renamed.
But don't you need to add a --reintegrate flag if you want to merge your branch several times? It's mentioned here [snip] Neither Git nor Mercurial has has such a flag and both let you keep working with your branches after merging them (in any direction).
I do not need the "--reintegrate" flag. svn 1.6 keeps track of merge information, and even before that I knew when the branch was created. I've been working with branches in svn for some time and only lately it occurred to me what the workflow using "--reintegrate" is.
I had to re-read this section: http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.branchemerge.basicmergi... It points out that the --reintegrate flag is critical for reintegrating changes from a branch back into trunk. They are talking about a scenario where you've continuously kept the branch up to date with changes from trunk and now want to merge back: trunk: a --- b --- c --- d --- e \ \ branch: r --- s --- t --- u Because of the t revision, you cannot just replay the r:u changes on top of e: the u revision already contain some of the changes that are in e (the b and c changes).
I guess this is easier in hg or git.
Yes, in those systems you would do a final merge from the mainline into your branch: default: a --- b --- c --- d --- e \ \ \ branch: r --- s --- t --- u --- v Merging back to default is now a no-op! Technically you try to do a merge between e and v. You find their common ancestor (e!) and you now have a degenerate three-way merge where the state in v wins every time. So you can create default: a --- b --- c --- d --- e - f \ \ \ / branch: r --- s --- t --- u --- v where the files in f look exactly like they do in v. There have often been a few changes on default since the last branch synchronization so you really start with default: a --- b --- c --- d --- e --- f --- g \ \ \ branch: r --- s --- t --- u --- v and merge g and v. Here the ancestor is e (close by!) so you only have to consider changes made in f and g. The final state is then: default: a --- b --- c --- d --- e --- f --- g --- h \ \ \ / branch: r --- s --- t --- u --- v ------------' Three-way merges are *symmetric* in Git and Mercurial and so it doesn't matter which way you merge -- you get the same amount of conflicts.
Could you try repeating the above commands with a rename in your branch and an edit in trunk?
I already tried your example before, and yes, I got a conflict. And I was not able to work around this.
BTW, as I understand git: the working copy contains a hidden directory that stores all of the repository data. And the checkout will be placed at top-level. Is there a way to checkout multiple branches at the same time?
Yes, you can do that with both systems. With Mercurial you make a new clone based on an existing local repository: hg clone my-repo my-second-repo cd my-second-repo hg update my-favorite-branch That gives you two independent working copies. By making a local clone you avoid downloading anything again. Furthermore, a local clone will make *hardlinks* between the files in the .hg/ directory. This means that both clones share the disk space: you only pay for creating a new working copy. So you end up with two checkouts and both have the full history inside their .hg/ directories. But the disk space is shared so the overhead is very low. With SVN you would have to make a new 'svn checkout' -- or I guess you can copy an existing checkout with 'cp' and then 'svn switch'? That way you avoid downloading the files that aren't affected by the switch. Notice a fundamental difference in design here: Mercurial (and Git) have branches. Subversion don't: http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.branchmerge.using.conce... Instead, SVN has a cheap server-side copy mechanism and SVN allows you to checkout a single subdirectory at a time. SVN also allows you to merge changes made in a subdirectory into another subdirectory. These features let you "emulate" branches and tags, but they are not first-class citizens in the system. This in turn allows SVN to represent a richer history than Git and Mercurial. That is, I can do svn cp ^/trunk/foo/bar ^/tags/bar-1.0 -m "branch" to "tag" a random subdirectory. That operation doesn't make any sense in the other systems: there a tag references a commit and that's that. Depending on your viewpoint, you can say that Git and Mercurial models the history in a more clean way. You can also say that they lack a crucial feature :) -- Martin Geisler aragost Trifork Professional Mercurial support http://www.aragost.com/mercurial/