0

I've been using git for quite a while but I never really understood why merge conflicts happen. I learnt to resolve them quickly but I feel like not understanding why they happen makes me unhappy. The most common explanation is the same code region was changed by 2 different commits and now git cannot decide which one to pick makes sense only for the simplest cases.

In order to understand better what's going on I created a simple file with 2 lines:

a
b

and commited it (log message init, branch master).

Then I created a feat branch from master and added a 3rd line: c

Then I created another feat2 branch from master and changed b to bb.

Finally, I changed the first line in master to ax.

The resulting tree looks like this:

$ git tree
* f4c4a9d (feat) add 3rd line: c
| * f050bf8 (feat2) changed 2nd line: b -> bb
|/  
| * 244ed21 (HEAD -> master) change 1st line: a -> ax
|/  
* 51fca0f init

If I want to cherry-pick or merge feat into master it works fine but if I want to cherry-pick feat2 which changes the 2nd line it fails and can't figure out why that happens.

theluckyemil
  • 663
  • 1
  • 7
  • 16
  • If you don't mind sitting down to read, you might want to take a look at something that i am writing about the subject: http://ezconflict.com (no tracking, no monetizing) – eftshift0 Dec 11 '20 at 20:05
  • Duplicate of (for example): [Why changes in another line arise git merge conflict?](https://stackoverflow.com/questions/63625742/why-changes-in-another-line-arise-git-merge-conflict) As eftshift0 has already explained there, if one branch (master) changes the first line, and the other branch (feat2) changes the second line, that's too close together: it counts as changing the same thing two different ways, i.e. a conflict. – matt Dec 12 '20 at 01:04
  • The _reasons_ why it counts as the same thing are a bit complicated, but it has to do with the diffing algorithm (see https://stackoverflow.com/questions/55275340/why-do-changing-adjacent-lines-but-modifying-independently-cause-a-git-merge-con) – matt Dec 12 '20 at 01:08

2 Answers2

1

In order for git to be able to apply a change, git needs to be able to get common boundaries between the sections that are being affected. If no common lines exist in the merge process (keep in mind that a cherry-pick is like a normal merge, the only trick is that what is taken as what is the common ancestor in a normal merge, in a cherry-pick it is forced to be the parent of the revision you are cherry-picking), then git will just show you a conflict block.

Keep in mind that you are considering not 2 versions of the file, but three.

One version is the common ancestor (in your case, it really is the common ancestor, but in a cherry-pick that is normally not the case):

a
b

The tip of master:

ax
b

feat2:

a
bb

If you consider what remains without change between the 3 versions, nothing survived.... so not much that git can do to figure out what should happen. You get a conflict. If there had been a single unchanged line between the a and b, there would be no problem. Try the same changes on a and b but starting from this file on the first revision:

a
x
b

Then git will have no problem cherry-picking. It might make more sense if you tried merging using merge.conflictStyle set to diff3 so that you can see how code is in the 3 versions involved.

Side note: if you don't mind sitting down to read, you might want to take a look at something that i am writing on the subject (no monetizing, no tracking): http://www.ezconflict.com

eftshift0
  • 26,375
  • 3
  • 36
  • 60
1

The most common explanation is the same code region was changed by 2 different commits and now git cannot decide which one to pick makes sense only for the simplest cases.

Well, no... that is the explanation, and it applies to all cases. The detail you may be missing is, if there isn't at least one unchagned line between the lines affected by "our" changes and the lines affected by "their" changes, then the changes are considered overlapping.

So in your example:

In master you changed line one.

In one of the branches you added line 3; since line 2 is between them, this is not a conflict.

But in the other branch you changed line 2. There is no line between lines 1 and 2, so this would conflict with the change on master; and additionally it would conflict with the addition of line 3 in the other branch (since there are no lines between line 2 and line 3).

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52