manidos
manidos

Reputation: 3464

Automatic merge conflict resolution

I get a merge conflict in index.js when running this:

$ git checkout feature
$ git merge master

The feature branch index.js

const a = 1;
const b = 1;

The master branch index.js (This is where feature branch was born)

 const a = 1;

The master branch index.js (Current state)

 const a = 2;

I want automatically resolve the conflict in such a way so that index.js on feature branch was updated to this:

const a = 2;
const b = 1;

Upvotes: 0

Views: 4499

Answers (2)

torek
torek

Reputation: 487725

I would advise against using -X ours or -X theirs (or their longer spelling equivalents, --strategy-option ours and the like) here.

The conflict that Git sees—remember, Git works line-by-line—is that in the merge base commit Git sees:

const a = 1;

In one of the two branch tip commits (let's call this the left hand side or ours one) Git sees:

const a = 1;
const b = 1;

This, to Git, looks like:

  • at the a=1 line (which matches) add const b = 1;

Meanwhile, in the other branch tip commit, theirs or the right hand side, Git sees:

const a = 2;

To Git, this looks like:

  • at the a=1 line delete a line, and insert const a = 2; instead

Both instructions "touch" the a=1 line, so Git declares a conflict.

If you tell Git to favor "ours" / the left hand side, Git will keep the add b = 1 line instruction, and throw away the delete a = 1 and insert replacement line instruction. If you tell Git to favor "theirs" / the right hand side, Git will keep the instruction that replaces a=1 with a=2, but will throw away the other instruction.

Either way, you'll end up with the wrong resolution. The right resolution is actually to accept both changes even though they appear to conflict. Git has no way to do that automatically.

What I like to do for this case is to set merge.conflictStyle to diff3. That way, when Git leaves the messy merge conflict result in my work-tree, the file reads:

<<<<<<< HEAD
const int a = 1;
const int b = 1;
||||||| merged common ancestor
const int a = 1;
=======
const int a = 2;
>>>>>>> master

With the default, the seven vertical bars and const int a = 1; base lines are missing (and sometimes the remaining lines are squished together even more). It's very hard to read. With the diff3 style, the base lines are there: you can see what everyone started with, and make your own decision whether to take both changes, just one change, or some third alternative that's better than either.

(See also http://psung.blogspot.com/2011/02/reducing-merge-headaches-git-meets.html)

Upvotes: 2

Mike Faber
Mike Faber

Reputation: 481

Like the comments mentioned, Git is only so good at deciding how to put code together. You might be interested in merge strategy options though. You can run

git merge --strategy-option theirs or git merge --strategy-option ours

To favor either the source or the destination when it comes to conflicts. Read more about it here:

Resolve Git merge conflicts in favor of their changes during a pull

https://git-scm.com/docs/merge-strategies

Upvotes: 3

Related Questions