Re: [PATCH 7/7] xdiff: make diff3 the default conflictStyle

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Elijah Newren wrote:
> On Fri, Jun 11, 2021 at 8:32 AM Felipe Contreras <felipe.contreras@xxxxxxxxx>
> wrote:
> > Sergey Organov wrote:
> > > Junio C Hamano <gitster@xxxxxxxxx> writes:

> >   git init repo &&
> >   cd repo &&
> >
> >   echo 1 > content &&
> >   git add content &&
> >   git commit -m 1 content &&
> >
> >   git checkout -b A master &&
> >   echo A > content &&
> >   git commit -m A content &&
> >
> >   git checkout -b B master &&
> >   echo B > content &&
> >   git commit -m B content &&
> >
> >   git checkout -b C A &&
> >   git rev-parse B >.git/MERGE_HEAD &&
> >   echo C > content &&
> >   git commit -m C -a &&
> >
> >   git checkout -b D A &&
> >   git rev-parse B >.git/MERGE_HEAD &&
> >   echo D > content &&
> >   git commit -m D -a &&
> >
> >   git -c merge.conflictstyle=diff3 merge -m final C &&
> >   cat content
> 
> Right, here you do not have a unique merge base; you have two of them: A &
> B (it's possible to have three or more as well).  To do a three-way merge,
> you need a single base commit.  So, whenever you have more than one merge
> base, both merge-recursive and merge-ort will merge the merge bases to get
> a virtual merge base.  There's always a risk that the merge bases don't
> have a unique merge base either, forcing the algorithm to recurse.  This
> behavior is where the merge algorithm 'recursive' got its name from (and
> which also appears in ort's name -- "Ostensibly Recursive's Twin").
> 
> You could decide to just pick one of the merge-bases at random, and yield a
> different set of surprises including silently merging in favor of one side
> when the two sides did things differently.  That's problematic.
> 
> Instead of using a merge base (a recent-as-possible common commit), you
> could decide to instead just try to find a unique common base, regardless
> of how ancient it is.  Using ancient commits as the base is a step towards
> just doing a two-way merge (treating the histories as completely
> independent and throwing merge conflicts whenever any files aren't
> identical on the two sides).  Sure, it's not as bad, but it does yield
> massive amounts of useless conflicts.  So this is problematic too.
> 
> The alternative to the above two options was the
> make-a-virtual-merge-base-by-merging-merge-bases strategy.  It apparently
> was very successful.

OK. That makes sense.

> But it does mean that merge bases can have conflict markers in them.

But why? And even if they do, why do they have to be diff3 conflict
markers?

This would be more human-friendly:

  <<<<<<< HEAD
  D
  ||||||| merged common ancestors
  <<<<<<<<< Temporary merge branch 1
  B
  =========
  A
  >>>>>>>>> Temporary merge branch 2
  =======
  C
  >>>>>>> C

Or just put a stub conflict marker:

  <<<<<<< HEAD
  D
  ||||||| merged common ancestors
  <<<<<<<<< Temporary merge >>>>>>>>>
  =======
  C
  >>>>>>> C

Or just use the base of the virtual merge:

  <<<<<<< HEAD
  D
  ||||||| merged common ancestors
  1
  =======
  C
  >>>>>>> C

We don't have to use diff3 all the way.

Cheers.

-- 
Felipe Contreras



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux