How andor why is merging in Git better than in SVN

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

I ve heard in a few places that one of the main reasons why distributed version control systems shine, is much better merging than in traditional tools like SVN. Is this actually due to inherent differences in how the two systems work, or do specific DVCS implementations like Git/Mercurial just have cleverer merging algorithms than SVN?

Answers

http://svn.apache.org/repos/asf/subversion/trunk/notes/merge-tracking/index.html http://svn.apache.org/repos/asf/subversion/trunk/notes/merge-tracking/index.html

So why did Subversion merges suck  ?

Ponder this example:

      1   2   4     6     8
trunk o-->o-->o---->o---->o
       
           3     5     7
b1       +->o---->o---->o

http://svnbook.red-bean.com/en/1.1/ch04s03.html http://svnbook.red-bean.com/en/1.1/ch04s03.html

svn merge -r 2:7 {link to branch b1}

… which will attempt to merge the changes from b1 into your local working directory. And then you commit the changes after you resolve any conflicts and tested the result. When you commit the revision tree would look like this:

      1   2   4     6     8   9
trunk o-->o-->o---->o---->o-->o      "the merge commit is at r9"
       
           3     5     7
b1       +->o---->o---->o

However this way of specifying ranges of revisions gets quickly out of hand when the version tree grows as subversion didn t have any meta data on when and what revisions got merged together. Ponder on what happens later:

           12        14
trunk  …-->o-------->o
                                     "Okay, so when did we merge last time?"
              13        15
b1     …----->o-------->o

This is largely an issue by the repository design that Subversion has, in order to create a branch you need to create a new virtual directory in the repository which will house a copy of the trunk but it doesn t store any information regarding when and what things got merged back in. That will lead to nasty merge conflicts at times. What was even worse is that Subversion used two-way merging by default, which has some crippling limitations in automatic merging when two branch heads are not compared with their common ancestor.

To mitigate this Subversion now stores meta data for branch and merge. That would solve all problems right?

And oh, by the way, Subversion still sucks…

On a centralized system, like subversion, virtual directories suck. Why? Because everyone has access to view them… even the garbage experimental ones. Branching is good if you want to experiment but you don t want to see everyones and their aunts experimentation . This is serious cognitive noise. The more branches you add, the more crap you ll get to see.

The more public branches you have in a repository the harder it will be to keep track of all the different branches. So the question you ll have is if the branch is still in development or if it is really dead which is hard to tell in any centralized version control system.

Most of the time, from what I ve seen, an organization will default to use one big branch anyway. Which is a shame because that in turn will be difficult to keep track of testing and release versions, and whatever else good comes from branching.

So why are DVCS, such as Git, Mercurial and Bazaar, better than Subversion at branching and merging?

There is a very simple reason why: branching is a first-class concept . There are no virtual directories by design and branches are hard objects in DVCS which it needs to be such in order to work simply with synchronization of repositories (i.e. push and pull ).

http://doc.bazaar.canonical.com/bzr.2.5/en/user-reference/branch-help.html http://doc.bazaar.canonical.com/bzr.2.5/en/user-reference/branch-help.html

http://en.wikipedia.org/wiki/Directed_acyclic_graph http://en.wikipedia.org/wiki/Directed_acyclic_graph

A very simple example of merging would be this; imagine a central repository called origin and a user, Alice, cloning the repository to her machine.

         a…   b…   c…
origin   o<---o<---o
                   ^master
         |
         | clone
         v

         a…   b…   c…
alice    o<---o<---o
                   ^master
                   ^origin/master

What happens during a clone is that every revision is copied to Alice exactly as they were (which is validated by the uniquely identifiable hash-id s), and marks where the origin s branches are at.

Alice then works on her repo, committing in her own repository and decides to push her changes:

         a…   b…   c…
origin   o<---o<---o
                   ^ master

              "what ll happen after a push?"


         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                   ^origin/master

The solution is rather simple, the only thing that the origin repository needs to do is to take in all the new revisions and move it s branch to the newest revision (which git calls "fast-forward"):

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

         a…   b…   c…   d…   e…
alice    o<---o<---o<---o<---o
                             ^master
                             ^origin/master

The use case, which I illustrated above, doesn t even need to merge anything . So the issue really isn t with merging algorithms since three-way merge algorithm is pretty much the same between all version control systems. The issue is more about structure than anything .

So how about you show me an example that has a real merge?

Admittedly the above example is a very simple use case, so lets do a much more twisted one albeit a more common one. Remember that origin started out with three revisions? Well, the guy who did them, lets call him Bob , has been working on his own and made a commit on his own repository:

         a…   b…   c…   f…
bob      o<---o<---o<---o
                        ^ master
                   ^ origin/master

                   "can Bob push his changes?" 

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

http://www.imdb.com/title/tt0062622/quotes http://www.imdb.com/title/tt0062622/quotes

http://doc.bazaar.canonical.com/bzr.2.5/en/user-reference/merge-help.html http://doc.bazaar.canonical.com/bzr.2.5/en/user-reference/merge-help.html

                        v master
         a…   b…   c…   f…
bob      o<---o<---o<---o
                   ^
                   |    d…   e…
                   +----o<---o
                             ^ origin/master

         a…   b…   c…   d…   e…
origin   o<---o<---o<---o<---o
                             ^ master

The second step of the pull process is to merge the diverging tips and make a commit of the result:

                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+
                             ^ origin/master

http://ftp.sunet.se/pub/Linux/kernel.org/software/scm/git/docs/git-merge.html http://ftp.sunet.se/pub/Linux/kernel.org/software/scm/git/docs/git-merge.html

                                 v origin/master
                                 v master
         a…   b…   c…   f…       1…
bob      o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

                                 v master
         a…   b…   c…   f…       1…
origin   o<---o<---o<---o<-------o
                   ^             |
                   |    d…   e…  |
                   +----o<---o<--+

http://doc.bazaar.canonical.com/beta/en/user-guide/adv_merging.html#rebasing http://doc.bazaar.canonical.com/beta/en/user-guide/adv_merging.html#rebasing

As an exercise for the reader, try drawing out how it ll work out with another user involved. It is similarly done as the example above with Bob. Merging between repositories is easier than what you d think because all the revisions/commits are uniquely identifiable.

http://martinfowler.com/bliki/FeatureBranch.html http://martinfowler.com/bliki/FeatureBranch.html

Because the structure is different from Subversion, by instead employing a DAG, it enables branching and merging to be done in an easier manner not only for the system but for the user as well.

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/2471606/how-and-or-why-is-merging-in-git-better-than-in-svn

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils