Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can git merge two files ignoring their common ancestor

Tags:

git

For example I have the following file:

// first part
function() {
    var timer = 1;
}

// second part
function() {
    var timer = 2;
}

// third part
function() {
    var timer = 3;
}

Now two different branches change it. I have changes:
in branch1:

// first part
function() {
    var timer = "changed in branch1";
}

// second part
function() {
    var timer = 2;
}

// third part
function() {
    var timer = 3;
}

in branch2:

// first part
function() {
    var timer = 1;
}

// second part
function() {
    var timer = "changed in branch2";
}

// third part
function() {
    var timer = 3;
}

With 3-way merge these changes will merge clean because each branch changed a chunk of code different from the other one. However, when merged I want the following:

// first part
function() {
<<<<<<< branch1
    var timer = "changed in branch1";
=======
    var timer = 1;
>>>>>>> branch2
}

// second part
function() {
<<<<<<< branch1
    var timer = 2;
=======
    var timer = "changed in branch2";
>>>>>>> branch2
}

// third part
function() {
    var timer = 3;
}

Is there any way to achieve this kind of merge in git? I assume based on the comments this kind of merge would be something like this:

  1. make diff of a file
  2. insert in the final version chunks not in a diff
  3. mark chunks that differ with conflict markers
like image 318
Max Koretskyi Avatar asked Mar 27 '15 07:03

Max Koretskyi


2 Answers

Git offers the plumbing command git merge-file that will allow you to do a merge of two files without a base, however there is not a simple way to invoke this. If you are merging branch into master and want to do a baseless merge of some file foo.txt:

git show master:foo.txt > /tmp/master.foo.txt
git show branch:foo.txt > /tmp/branch.foo.txt
echo -n > /tmp/empty.txt
git merge-file -p -L master -L base -L branch /tmp/master.foo.txt /tmp/empty.txt /tmp/branch.foo.txt > foo.txt

In the above example, this produces:

// first part
function() {
<<<<<<< master
    var timer = 1;
=======
    var timer = "changed in branch1";
>>>>>>> branch
}

// second part
function() {
<<<<<<< master
    var timer = "changed in branch2";
=======
    var timer = 2;
>>>>>>> branch
}

// third part
function() {
    var timer = 3;
}

(Scripting this is left as an exercise for the reader.)

like image 124
Edward Thomson Avatar answered Nov 15 '22 05:11

Edward Thomson


If you just want to see the differences between your code and a certain commit, just do:

git diff HEAD..<sha-commit2>

or if you want to compare current commit with the tip of another branch:

git diff HEAD..other_branch

EDIT As @Maximus asked in the comment: if you want to see the changes made by someone

  • on the master branch
  • in particular files
  • since the time you branched

So we need to find the common ancestor first: (I suppose you are on your branch; whence I am using HEAD. Can be replaced by your branch name)

git merge-base HEAD master

then you can see the changes since that common ancestor in particular files (git log -p or git diff; depends on the output you like):

git log -p <sha-common-ancestor>..master -- <the files and dirs you want>
git diff <sha-common-ancestor>..master -- <the files and dirs you want>
like image 45
Chris Maes Avatar answered Nov 15 '22 04:11

Chris Maes