Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Friday, February 12, 2016

Really, a concrete example that merging in Git is easier than SVN?

Really, a concrete example that merging in Git is easier than SVN?


Stack Overflow question How and/or why is merging in Git better than in SVN? is a great question with some great answers. However none of them show a simple example where merging in Git works better than SVN.

On the chance this question will be closed as a duplicate, what is

  1. A concrete merge scenario
  2. How it is difficult in SVN?
  3. How the same merge is easier in Git?

A few points:

  • No philosophy or deep explanations of what a DVCS is please. These are great, really, but I don't want their details to obfuscate the answer to this (IMHO) important
  • I don't care about "historic SVN" at the moment. Please compare modern Git (1.7.5) to modern SVN (1.6.15).
  • No renames please - I know that Git detects renames and moves, while SVN doesn't. This is great, but I am looking for something deeper, and example that doesn't involve renames or moves.
  • No rebase or other 'advanced' Git operation. Just show me the merge please.

Answer by Greg Hewgill for Really, a concrete example that merging in Git is easier than SVN?


From a practical perspective, merging has traditionally been "hard" because of what I call the "big bang merge" problem. Suppose a developer has been working away on some code for a while and hasn't committed their work yet (maybe the developer is accustomed to working in Subversion against trunk, and doesn't commit unfinished code). When the developer finally commits, there is going to be a lot of changes all rolled up into one commit. For the other developers who want to merge their work with this "big bang" commit, the VCS tool isn't going to have enough information about how the first developer got to the point they committed, so you just get "here's a giant conflict in this whole function, go fix it".

On the other hand, the usual style of working with Git and other DVCS that have cheap local branches, is to commit regularly. Once you've done one bit of work that pretty much makes sense, you commit it. It doesn't have to be perfect but it should be a coherent unit of work. When you come back to merge, you still have that history of smaller commits that shows how you got from the original state to the current state. When the DVCS goes to merge this with the work of others, it has a lot more information about what changes were made when, and you end up getting smaller and fewer conflicts.

The point is that you can still make merging a hard problem with Git by making a single big bang commit only after you've finished something. Git encourages you to make smaller commits (by making them as painless as possible), which makes future merging easier.

Answer by Jakub Narbski for Really, a concrete example that merging in Git is easier than SVN?


I don't have concrete examples, but any kind of repeated merge is difficult, in particular so called criss-cross merge.

   a    / \   b1  c1   |\ /|   | X |   |/ \|   b2  c2  

merging b2 and c2


The wiki page on Subversion Wiki describing differences between mergeinfo based assymetric Subversion merge (with 'sync' and 'reintegrate' directions) and merge tracking based symmetric merge in DVCS has a section "Symmetric Merge with Criss-Cross Merge"

Answer by TheGreyMatter for Really, a concrete example that merging in Git is easier than SVN?


Keeping the answer short - In DVCS , since you have a local source control, if something get screwed up in the merge process (which will probably happen in large merges), you can always rollback to a previous local version which has the changes you've made before merging, and then try again.

So basically you can do merge without the fear that your local changes might get damaged during the process.

Answer by Ingo Blackman for Really, a concrete example that merging in Git is easier than SVN?


I can only tell you of a small experiment were Git was NOT better than Subversion (same problems).

I was wondering about this case: You start with two branches "mytest1" and "mytest2" both based on the same commit. You have got a C file which contains a function blub(). In branch mytest1 you move "blub()" to a different position in the file and commit. In branch mytest2 you modify blub() and commit. On branch mytest2 you try to use "git merge mytest1".

Seems to give a merge conflict. I hoped that Git would recognize that "blub()" was moved in mytest1 and then be able to auto-merge the modification in mytest2 with the move in mytest1. But at least when I tried this did not work automatically...

So while I fully understand that Git is much better at tracking what has been merged and what has not been merged yet, I also wonder if there is "pure" merge case in which Git is better than SVN...

Now because this question has been bugging me for a long time I was really trying to create a concrete example where Git is better, whereas merging in SVN fails.

I found one here http://stackoverflow.com/a/2486662/1917520, but this includes a rename and the question here was for a case without a rename.

So here is an SVN example which basically tries this:

bob        +-----r3----r5---r6---+            /                /      \  anna     /  +-r2----r4----+--+     \          /  /                  \     \  trunk  r1-+-------------------r7-- Conflict  

The idea here is:

  • Anna and Bob are both developers with their own branches (created in r2,r3).
  • Anna does some modifications (r4),
  • Bob does some modifications (r5).
  • Bob merges the modifications from Anna into his branch; this gives conflicts, which Bob fixes and then commits (r6).
  • Annas modifications are merged back into the trunk (r7).
  • Bob tries to merge his modification back into the trunk and this again gives a conflict.

Here is a Bash script, which produces this conflict (using SVN 1.6.17 and also SVN 1.7.9):

#!/bin/bash  cd /tmp  rm -rf rep2 wk2  svnadmin create rep2  svn co file:///tmp/rep2 wk2  cd wk2  mkdir trunk  mkdir branches  echo -e "A\nA\nB\nB" > trunk/f.txt  svn add trunk branches  svn commit -m "Initial file"  svn copy ^/trunk ^/branches/anna -m "Created branch anna"  svn copy ^/trunk ^/branches/bob  -m "Created branch bob"  svn up   echo -e "A\nMA\nA\nB\nB" > branches/anna/f.txt  svn commit -m "anna added text"  echo -e "A\nMB\nA\nB\nMB\nB" > branches/bob/f.txt  svn commit -m "bob added text"  svn up  svn merge --accept postpone ^/branches/anna branches/bob  echo -e "A\nMAB\nA\nB\nMB\nB" > branches/bob/f.txt  svn resolved branches/bob/f.txt  svn commit -m "anna merged into bob with conflict"  svn up  svn merge --reintegrate ^/branches/anna trunk  svn commit -m "anna reintegrated into trunk"  svn up  svn merge --reintegrate --dry-run ^/branches/bob trunk  

The last "--dry-run" tells you, that there will be a conflict. If you instead first try to merge Anna's reintegration into Bob's branch then you also get a conflict; so if you replace the last svn merge with

svn merge ^/trunk branches/bob  

this also shows a conflicts.

Here is the same with Git 1.7.9.5:

#!/bin/bash  cd /tmp  rm -rf rep2  mkdir rep2  cd rep2  git init .  echo -e "A\nA\nB\nB" > f.txt  git add f.txt  git commit -m "Initial file"  git branch anna  git branch bob  git checkout anna  echo -e "A\nMA\nA\nB\nB" > f.txt  git commit -a -m "anna added text"  git checkout bob  echo -e "A\nMB\nA\nB\nMB\nB" > f.txt  git commit -a -m "bob added text"  git merge anna  echo -e "A\nMAB\nA\nB\nMB\nB" > f.txt  git commit -a -m "anna merged into bob with conflict"  git checkout master  git merge anna  git merge bob  

The contents of f.txt change like this.

Initial version

A  A  B  B  

Anna's modifications

A  MA  A  B  B  

Bob's modifications

A  MB  A  B  MB  B  

After Anna's branch is merged into Bob's branch

A  MAB  A  B  MB  B  

As so many people already pointed out: The problem is, that subversion cannot remember that Bob already resolved a conflict. So when you try to now merge Bob's branch into the trunk, then you have to re-resolve the conflict.

Answer by Lazy Badger for Really, a concrete example that merging in Git is easier than SVN?


If you exclude "Merge-Refactored Hell" you will not get fair samples, because they just doesn't exist

Answer by Spoike for Really, a concrete example that merging in Git is easier than SVN?


The most concrete example I can think of is the simplest merge that does not result in merge conflicts. However (TL;DR) with that example Git is still inherently a simpler procedure than with Subversion. Lets review why:

Subversion

Consider the following scenario in subversion; the trunk and the feature branch:

   1  2  3  ?--o--o--o              trunk            \4  5             o--o         branches/feature_1  

To merge you can use the following command in subversion:

# thank goodness for the addition of the --reintegrate flag in SVN 1.5, eh?  svn merge --reintegrate central/repo/path/to/branches/feature_1    # build, test, and then... commit the merge  svn commit -m "Merged feature_1 into trunk!"  

In subversion merging the changes requires another commit. This is to publish the changes that the merge did with applying the changes on the feature branch virtual directory back into the trunk. That way everyone working with the trunk can now use it and the revision graph looks like sort of like this:

   1  2  3      6  ?--o--o--o------o       /trunk            \4  5/             o--o         /branches/feature_1  

Lets see how this is done in git.

Git

In Git this merge commit is really not necessary as branches are glorified bookmarks on the revision graph. So with the same kind of revision graph structure it sort of looks like this:

         v-- master, HEAD       1  2  3  ?--o--o--o            \4  5             o--o                  ^-- feature_branch  

With the head currently on the master branch we can perform a simple merge with the feature branch:

# Attempt a merge  git merge feature_branch    # build, test, and then... I am done with the merge  

... and it will fast-forward the branch over to the commit where feature branch is pointing at. This is made possible because Git knows that the goal of the merge is a direct descendant and the current branch only needs to take in all the changes that happened. The revision graph will end up looking like this:

   1  2  3  4  5  ?--o--o--o--o--o                 ^-- feature_branch, master, HEAD  

The changes does not need a new commit as all git has done is to move the branch references further up to the front. All that is left is to publish this to the public repository if you have any:

# build, test, and then... just publish it  git push  

Conclusion

Given this simple scenario you can assert two things in the difference between Subversion and Git:

  • SVN requires at least a couple of commands to finalize the merge and forces you to publish your merge as a commit.
  • Git only requires one command and does not force you to publish your merge.

Given this to be the most simplest merge scenario it is difficult to argue that subversion is easier than git.

In more difficult merge scenarios, git also provides you the ability to rebase the branch that produces a simpler revision graph at the cost of history rewriting. Once you get the hang of it though, and avoid publishing history rewrites of things already published, it isn't really that bad of a thing to do.

Interactive rebases is outside the scope of the question but to be honest; it enables you the ability to rearrange, squish and remove commits. I wouldn't willingly want to switch back to Subversion as history rewriting is not possible by design.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.