git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Rename conflicts in the index

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 27, 2013, 19:44 UTC
Message-ID
<7v38vgmxty.fsf@alter.siamese.dyndns.org>
In-Reply-To
<A54CE3E330039942B33B670D971F857403A0BB93@TK5EX14MBXC253.redmond.corp.microsoft.com>
Edward Thomson <ethomson@microsoft.com> writes:
Show 7 quoted lines
> Junio C Hamano [mailto:gitster@pobox.com] wrote:
>> We do not gratuitously break existing implementations.  If no conflict is stored
>> as higher-stage index entries in an index that has your index extension, no
>> existing implementation can read a conflicted index written by your
>> implementation and have users resolve conflicts.
>
> I'm not suggesting that anybody stop writing >0 stage entries.
Ah, OK, then I misread your original message.  You said
> Having a single canonical location is preferable - if the index
> contains a CONF section (and the client supports it), it would use
> that.  Otherwise, the client would look at stage >0 entries.

which I read as "an index with this extension would not have higher stage entries, an index without the extension records higher stage entries". As long as the format will be backward compatible to allow existing users use existing tools to deal with cases the existing tools can handle, then that is OK. I didn't get that impression which is where my "non starter" came from.

> What you've described is true only for a certain class of rename conflicts,
> for example the rename/edit conflict you've described above.

As you asked me to explain why it was a non starter, I only illustrated with a "renamed trivially, with content level conflict" example that shows why dropping higher-stage entries in the main index would not be acceptable. The previous message did not even mean to cover any cases the *new* feature you have in mind is trying to address. Again, if it hurts existing users handling cases existing tools used to handle, that makes it a non starter.

How new feature is designed, and extension is added to help that new feature, is a different matter. My original "That's a non starter" message didn't even go that far.

In any case, the principle of "always record the state 'merge' stopped to ask for help as higher stage entries to give existing tools and users a chance to manually resolve, and augment with optional extension to record additional information that might help, but do not gratiutously waste bytes on redundant information" would apply to other exotic cases you would want to tackle with the new feature, I would think.

If one branch moves path A in the original to path B and the other one moved it to path C, for example, we can record it in different ways, even in the main index.

 * Path A may have only stage #1, while path B and C has only stage
   #2 and stage #3 (the user would have to notice these three
   correspond to each other, and resolve manually).
   You would want to annotate "B at stage #2 seems to have been at A
   in the original" (similarly for C#3) if you choose to do so.
 * You can choose to favor "our" choice, and have path B with three
   stages (if we guessed wrong and the user wants to move it to C,
   the user can resolve and then "git mv" the path).
   You would want to annotate "the other side wanted to have B at
   stage #3 at C" in that case.
 * Or you may want to have in the main index both B and C (but not
   A) with all three stages (the user would have to choose which
   one survives, but discarding the other side with "git rm" would
   be easy).
   You would want to annotate the origin of the stage #1 for path B
   and C (these were originally at A), stage #2 for B (the other
   branch wants to have it at C), stage #3 for C (we want to have it
   at B).

There may be other ways, and I do not offhand know what the current merge-recursive implementation does, but both of the latter two sound equally usable and reasonable ways, even without the annotation. And with your annotation that records different paths, the conflict may become even easier to resolve.

I still do not need to duplicate <mode, SHA-1> in the extensions to do the above, or do I?

If the original path A was removed and a new path B was added, with contents that are modified from A beyond recognition, at the merge time you wouldn't know where B it came from or where A went, so annotating A at stage #1 to say "it went to B" is a nonsense. If you have algorithm to do so [*1*], you would be better off detecting it as a rename.

[Footnote]
*1* Instead of a three-way merge that inspects only the endpoints,
    you might get a better rename trail if you looked at the
    histories of both branches.  It would be a lot more expensive
    than the simple three-way, but burning CPU cycles is better than
    burning human neurons.
Previous: Edward ThomsonNext: Edward Thomson
Message 10 of 16 in “Rename conflicts in the index”
  1. Edward ThomsonMar 13, 2013
  2. Junio C HamanoMar 13, 2013
  3. Edward ThomsonMar 13, 2013
  4. Edward ThomsonMar 26, 2013
  5. Junio C HamanoMar 26, 2013
  6. Edward ThomsonMar 26, 2013
  7. Edward ThomsonMar 27, 2013
  8. Junio C HamanoMar 27, 2013
  9. Edward ThomsonMar 27, 2013
  10. Junio C HamanoMar 27, 2013
  11. Edward ThomsonApr 1, 2013
  12. Edward ThomsonApr 2, 2013
  13. Junio C HamanoApr 2, 2013
  14. Edward ThomsonApr 2, 2013
  15. Junio C HamanoApr 3, 2013
  16. Junio C HamanoApr 3, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.