Subject: Re: Summer of Code project ideas due this Friday

From: Junio C Hamano <[email-masked]>
Date: Thu, 10 Mar 2011 12:54:29 -0800

Jeff King <[email-masked]> writes:

>> I think the end-result would be a nice feature. I suspect that it would
>> not involve conversion from --cc, but more like using the difference
>> between the HEAD and the working tree, generated as if there is no
>> multi-stage index.
>
> The trouble is that I would like to see the combined diff, then say "OK"
> and have it apply the result to the index. But because we work on a
> per-hunk basis, you need to match the combined diff hunks to the regular
> diff hunks, taking into account that hunks could be split.  Which maybe
> is straightforward, but I haven't convinced myself yet that there are no
> corner cases where they don't line up.

Forgetting for now the implementation, I _think_ what you would want is
for "git add -p" to notice that you are resolving conflicts, and do not
bother you about cleanly merged parts (I take it is a given that you would
always want to add them to the index without even inspecting when running
"add -p"), and make the per-hunk selection loop ask only about the parts
that originally had conflicts.

But it is rather hard to arrange.  Neither "--cc" nor "-c" during the
merge is about showing conflicts but is about showing the result with
respect to the two originals.  If you resolved conflicts in your editor
already, there are no lines with "<<</>>>" markers that are different from
either original to cause the "conflicted parts" to appear in their output.
If your conflict resolution ended up in taking what one side did, "--cc"
will hide it as a non-event.  So at least you would be using "-c" to
implement this.

Also, you have to remember that "add -p" is about adding the state you
deem Ok incrementally to the index, that once you add a path to the index
the higher stages for the path will collapse to stage #0, and that "-c"
and "--cc" make their comparison based on what you have in higher stages.

I would imagine that a workable implementation might look like this:

 0. The solution introduces a new index extension, "PRSF" (partial
    resolution so far)".  This is a mapping from pathname to a blob object
    name.

 1. "git add -p" notices that you are in the middle of conflict
    resolution, by noticing that you have higher stages to the path.

 2. Look up the path from the PRSF extension.  If there is no entry for
    the path, recreate the content-level 3-way merge using the content of
    three stages (i.e. the state immediately after the mergy operation
    that caused the conflicts before you touched the corresponding file in
    your working tree), and register this image (with the full glory of
    "<<</>>>" conflict markers) to the extension.  If there already is an
    entry in the extension for the path, skip this step.

 3. The patch the user will see in the interactive hunk selection is the
    difference between the working tree and the PRSF image, not your
    regular index (nor the HEAD version). This allows you to see how you
    resolved the conflict incrementally so far.

 4. Choosing a hunk to "apply" would not affect the index entry for the
    path, as it would collapse its higher stages.  It instead updates the
    blob registered in the PRSF extension using the hunk you are applying.

If you are running "git add -p" incrementally (i.e. edit a little, review
with diff, then "add -p" the part you are sure about, and repeat the whole
thing), the next invocation of "git add -p" would notice that you still
have unresolved conflicts in PRSF.  It will skip the step 2 above and the
step 3 will let you review the remaining difference between the PRSF image
(which you updated in step 4 during the last round) and what you have in
the working tree.  The step 4 will update the PRSF image for the next
invocation of "git add -p".  And you continue until you are done.

At the end (we would probably need a good way to detect the user might
want to declare "end" automatically for a good user experience), use the
PRSF image to collapse the higher stages for the path down to stage 0.