Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git merge -s recursive -X ours vs git merge -s ours?

Tags:

git

merge

In man git-merge doc, git merge -s recursive -X ours:

This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring our history contains all that happened in it.

I have tested these two but can't found the difference.

Is there an example to tell what is the difference between these two?

My git version is git version 1.8.3.4

like image 599
Tanky Woo Avatar asked May 20 '14 14:05

Tanky Woo


People also ask

What is Git merge recursive?

Recursive is the default merge strategy when pulling or merging one branch. Additionally this can detect and handle merges involving renames, but currently cannot make use of detected copies. This is the default merge strategy when pulling or merging one branch.

What is the difference between fast forward merge and recursive merge?

The merge commit continues to have two parents. Note: There is nothing right or wrong of either one of the strategies but with fast forward merge you have a straight line of history and with the recursive merge, it is of multiple lines.

What does Git merge ours do?

git merge -s ours. The ours strategy is simple: it discards all changes from the other branch. This leaves the content on your branch unchanged, and when you next merge from the other branch, Git will only consider changes made from this point forward.

What are the different Git merge types?

Git merging combines sequences of commits into one unified history of commits. There are two main ways Git will merge: Fast Forward and Three way. Git can automatically merge commits unless there are changes that conflict in both commit sequences.


2 Answers

As the man page says, -s ours ignores the contents of the other branch entirely. This should be obvious enough: no matter what's in the other branch, the tree attached to the merge commit is identical to the tree in the HEAD commit before the merge.

What -X ours does is more subtle: it uses "our" version of a change only when there's a conflict.

Here's a relatively simple example.

Suppose that you're on branch br1 and you ask to merge in branch br2. We'll make these really simple, with commit B (the merge base origin for both branches) having one single commit K on branch br1, and one single commit L on branch br2:

... - B - K   <-- HEAD=br1
        \
          L   <-- br2

Furthermore, the difference from B to K consists of only one item:

  • change (already existing) file f1: replace first line dog with cat

Meanwhile, the difference from B to L consists of:

  • change file f1: replace first line dog with poodle
  • change file f2: replace last line elephant with rhinoceros

When you merge these with no strategy or options, there will be a conflict in file f1 (different changes to the same lines), but not in f2 (the merge commit would take the change in commit L so that file f2 would change).

If you use:

git merge -s ours br2

the merge command will use "our" version of file f1 (dog becomes cat), and also our version of file f2 (elephant is not changed).

If you use:

git merge -s recursive -X ours

the merge command will find a conflict on file f1 and will resolve it in favor of our version—this is the same as before—but there is no conflict on file f2, so git will use their version of f2 (elephant becomes rhinoceros).

(This simple example does not show what happens if there are two different changes in different areas in f1 or f2. If f1 is long enough and there's a change in commit L further down than "the first line of the file", the merge can pick up that change since it won't conflict with the dog-to-cat change.)

like image 93
torek Avatar answered Oct 05 '22 08:10

torek


I don't know of any specific examples, but the difference is this:

git merge -s recursive -X ours

This does a "normal" merge (the recursive strategy is the default one), and when there are conflicts found, it attempts to resolve those conflicts by automatically using the code fragments from the branch being merged into ("ours"), rather than leaving conflict markers.

git merge -s ours

As the documentation you quoted says, this takes our version of the code, in it's entirety, and makes it the result of the merge - the other branch is not even looked at, no conflicts are detected, etc. It just simply says "make a new commit that looks like it merges the other branch in, but leave the resulting content exactly the way it looks right now in the current branch".

like image 23
twalberg Avatar answered Oct 05 '22 10:10

twalberg