git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
To: Edward Anderson <nilbus@nilbus.com>
Cc: git@vger.kernel.org
Subject: Re: No one understands diff3 "Temporary merge branch" conflict markers
Date: Tue, 07 Jul 2015 18:16:36 +0200	[thread overview]
Message-ID: <vpqbnfondsr.fsf@anie.imag.fr> (raw)
In-Reply-To: <CAOMsSXQVJsd0h1fnNMEJ5+cKpxbeF9mHraXva-wr6Y2zBCADbg@mail.gmail.com> (Edward Anderson's message of "Tue, 7 Jul 2015 10:55:05 -0400")

Edward Anderson <nilbus@nilbus.com> writes:

> I have the diff3 conflictstyle enabled and want to be able to
> understand how to understand its output when there are criss-cross
> merges requiring temporary merge branches.  Eg:
>
>     <<<<<<< HEAD
>       print(A);
>     ||||||| merged common ancestors
>     <<<<<<< Temporary merge branch 1
>       print(B);
>     =======
>       print(C);
>     >>>>>>> feature

I guess you are seeing the result of the recursive-merge.

>> The details are too advanced for this discussion, but the default
>> "recursive" merge strategy that git uses solves the answer by
>> merging a and b into a temporary commit and using *that* as the
>> merge base.

That is the point. We don't have a good common ancestor, so Git builds
one by merging the common ancestors. Then, two things can happen:

* The merge of the common ancestors is conflict-free. Then, we get a
  "sane" common ancestor.

* The merge has conflicts. In this case, the common ancestor that Git
  built has conflict markers. It is not a big issue, since when merging
  A, B, and ancestor(A, B), the result of the merge is either A or B,
  but never comes from ancestor(A, B). So, you never get to see the
  temporary ancestor(A, B), *except* when you request the common
  ancestor in the merge conflict.

It gets nasty since you get recursive merge conflicts, but you don't see
the recursivity. Let me try to indent your conflict:

 1 <<<<<<< HEAD
 2     unless admin
 3       fail Unauthorized.new("Admin only")
 4     end
 5 ||||||| merged common ancestors
 6         <<<<<<< Temporary merge branch 1
 7             unless admin
 8               fail Unauthorized.new("Admin only")
 9             end
10         ||||||| merged common ancestors
11             unless admin
12               fail Unauthorized.new
13             end
14         =======
15             fail Unauthorized.new unless admin
16         >>>>>>> Temporary merge branch 2
17 =======
18     unless admin
19         fail Unauthorized.new("Admin only")
20       fail Unauthorized.new
21     end
22 >>>>>>> feature

> It seems lines 6-16 are a conflict that occurred when merging the
> merge-bases.

Yes.

> That conflict could be resolved by merging the change in Temporary
> merge branch 1 (add "Admin only") with Temporary merge branch 2
> (convert multi-line unless to single-line) as this:
>
>            fail Unauthorized.new("Admin only") unless admin

That is probably what you would do if you resolved the conflict
manually, but while merging the common ancestors, Git found an ancestor
of an ancestor that was different from both ancestors being merged, and
there was a conflict. Asking you to resolve this conflict would be
essentially a loss of time since Git knows that the result won't appear
in the final merge, but only in the merge base.

 1 <<<<<<< HEAD
 2     unless feature.enabled_for_user?(UserIdLookup.new(params).user_id)
 3       fail Unauthorized.new("Requires setting #{label}.")
 4 ||||||| merged common ancestors
 5         <<<<<<< Temporary merge branch 1
 6             unless feature.enabled_for_user?(params[:user_id])
 7               fail Unauthorized.new("Requires setting #{label}.")
 8 =======
 9     unless feature.enabled_for_user?(params[:user_id])
10       fail Unauthorized.new("Requires setting #{label}.")
11 >>>>>>> feature

> This is the full conflict, and it doesn't seem to balance.

Right: I guess the merge-base was stg like

<<<<<<< Temporary merge branch 1
    unless feature.enabled_for_user?(params[:user_id])
      fail Unauthorized.new("Requires setting #{label}.")
|||||||
blabla 1
=======
blabla 2
>>>>>>> Temporary merge branch 2

But then, the actual merge happens, using this as merge-base. A conflict
occurs when the commits being merged and the merge-base are all
different. In your case, I guess the commits being merged were identical
on the next different hunks (the line "blablabla 1" probably was in both
commits being merged, which allowed the merge algorithm to move to the
next hunk), and there were no conflict in this hunk, hence you don't see
the merge base.

I hope this helps on the "light and understanding" part of your
question. Now, as of "what to do when I get this?", I would say: the
recursive merge-base was computed internally, but not really meant to be
shown to the user. You should probably ignore it and resolve the merge
by looking only at the 2 sides of the conflict ("ours" and "theirs").
Sorry, this is probably not the answer you expected, but it's the best I
can give ;-).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

  reply	other threads:[~2015-07-07 16:16 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-07 14:55 No one understands diff3 "Temporary merge branch" conflict markers Edward Anderson
2015-07-07 16:16 ` Matthieu Moy [this message]
2015-07-07 17:44   ` Junio C Hamano
2015-07-07 21:44     ` Matthieu Moy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=vpqbnfondsr.fsf@anie.imag.fr \
    --to=matthieu.moy@grenoble-inp.fr \
    --cc=git@vger.kernel.org \
    --cc=nilbus@nilbus.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).