Re: Rename conflicts in the index

3 messages, 2 authors, 2016-06-15 · open the first message on its own page

Re: Rename conflicts in the index

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:56:23

Edward Thomson [off-list ref] writes:
I would propose that we store the data about the file in conflict as it
occurred through the renames.  For example, in a rename 1->2 conflict where
A was renamed to both B and C, you would have a single conflict entry
containing the data for A, B and C.  This would allow us to provide more
detailed information to the user - and allow them to (say) choose a single
name to proceed with.

Is this something that has value to core git as well?  Alternately, is
there something particularly stupid about this proposal?
I do not offhand see anything particularly stupid; a new optional
index extension section CACHE_EXT_RENAME_CONFLICT might be a good
addition.

Is "one side moves A to B while the other side moves it to C" the
only case, or is it just an example?  Off the top of my head, "one
side moves A to x while the other side moves B to x/y" would also be
something we would want to know.  I am sure there are other cases
that need to be considered.

I do not think we can discuss the design at the concrete level until
the proposal spells out to cover all interesting cases in order for
implementations to agree on the common semantics.

RE: Rename conflicts in the index

From: Edward Thomson <hidden>
Date: 2016-06-15 22:56:23

Junio C Hamano [mailto:gitster@pobox.com] wrote:
I do not offhand see anything particularly stupid; a new optional index extension
section CACHE_EXT_RENAME_CONFLICT might be a good addition.

Is "one side moves A to B while the other side moves it to C" the only case, or is
it just an example?  Off the top of my head, "one side moves A to x while the
other side moves B to x/y" would also be something we would want to know.  I
am sure there are other cases that need to be considered.
Yes, that was just an example.  Certainly I was intending that all conflicts
that arose from renames would end up here since one can't really reason
why the merge tool created a conflict by looking at the index alone - even
knowing the merge tool's similarity algorithms, this would be awfully
expensive to piece back together, even if the index did contain non-zero
stage entries for all the items that were involved in the conflicts.

That said, my rather naive initial thought was that we could repeat *all*
conflicts in this area.  This would give tools that knew how to understand
this the ability to go to a single place for conflict data, rather than
producing some merge of high-stage entries that comprise non-rename
conflicts and data from the rename conflict area for rename conflicts.

Thanks-
-ed

RE: Rename conflicts in the index

From: Edward Thomson <hidden>
Date: 2016-06-15 22:56:31

Junio C Hamano [mailto:gitster@pobox.com] wrote:
Edward Thomson [off-list ref] writes:
quoted
I would propose that we store the data about the file in conflict as
it occurred through the renames.  For example, in a rename 1->2
conflict where A was renamed to both B and C, you would have a single
conflict entry containing the data for A, B and C.  This would allow
us to provide more detailed information to the user - and allow them
to (say) choose a single name to proceed with.

Is this something that has value to core git as well?  Alternately, is
there something particularly stupid about this proposal?
I do not offhand see anything particularly stupid; a new optional index extension
section CACHE_EXT_RENAME_CONFLICT might be a good addition.

Is "one side moves A to B while the other side moves it to C" the only case, or is
it just an example?  Off the top of my head, "one side moves A to x while the
other side moves B to x/y" would also be something we would want to know.  I
am sure there are other cases that need to be considered.

I do not think we can discuss the design at the concrete level until the proposal
spells out to cover all interesting cases in order for implementations to agree on
the common semantics.
Sorry about the delay here:  besides getting busy with some other things,
I wanted both a complete writeup and to have taken a pass at a test
implementation this in libgit2 to make sure seemed like a reasonably sensible
approach.

I would propose a new extension, 'CONF', to handle conflict data, differing
from the stage >0 entries in the index in that this extension tracks the
conflicting file across names if the underlying merge engine has support
for renames.

I made an attempt to keep the entry data similar to other entries in the
index.  I would propose that entries in the conflict are as follows:

Flags
  Four octets that describe the conflict.  Data includes:

  0x01  HAS_ANCESTOR
    There is a file in the common ancestor branch that contributes
    to this conflict.  Its data will follow.
  0x02  HAS_OURS
    There is a file in "our" branch that contributes to this conflict.
    Its data will follow.
  0x04  HAS_THEIRS
    There is a file in "their" branch that contributes to this conflict.
    Its data will follow.

  0x08  NAME_CONFLICT_OURS
    This item has a path in "our" branch that overlaps a different
    item in "their" branch.  (Eg, this conflict represents the "our"
    side of a rename/add conflict.)
  0x10  NAME_CONFLICT_THEIRS
    This item has a path in "their" branch that overlaps a different
    item in "our" branch.  (Eg, this conflict represents the "theirs"
    side of a rename/add conflict.)

  0x20  DF_CONFLICT_FILE
    This is the file involved in a directory/file conflict.
  0x40  DF_CONFLICT_CHILD
    This is a child of a directory involved in a directory/file conflict.

  Other bits are reserved.

Conflict Sides
  The data about one side of a conflict will contain:
  mode (ASCII string representation of octal, null-terminated)
  path (null terminated)
  sha1 (raw bytes)

The conflict sides will be written in this order:
  Ancestor (if HAS_ANCESTOR is set)
  Ours (if HAS_OURS is set)
  Theirs (if HAS_THEIRS is set)

I would propose that this not simply track rename conflicts, but all
conflicts.  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.

I would propose that another extension, 'RSVD', track these conflicts once
they are resolved.  The format would be the same - when a conflict is
resolved from the CONF the entry will be placed as-is in the RSVD.

Examples are not an exhaustive list, but should help elucidate the name
and d/f conflicts:

Normal edit / edit conflict, where A is edited in ours and theirs:

  Conflict one:
    Flags = HAS_ANCESTOR|HAS_OURS|HAS_THEIRS
    Entry 1 = A [Ancestor]
    Entry 2 = B [Ancestor]
    Entry 3 = C [Ancestor]

Rename / add conflict, where A is renamed to B in ours and B is added in
theirs:

  Conflict one:
    Flags = HAS_ANCESTOR|HAS_OURS|NAME_CONFLICT_OURS
    Entry 1 = A [Ancestor]
    Entry 2 = B [Ours]
    Entry 3 = A [Theirs]
  Conflict two:
    Flags = HAS_THEIRS|NAME_CONFLICT_THEIRS
    Entry 1 = File B [Theirs]

D/F conflict, where some file A is deleted in theirs, and a directory
A is created with file child:

  Conflict one:
    Flags = HAS_ANCESTOR|HAS_OURS|HAS_THEIRS|DF_CONFLICT_FILE
    Entry 1 = A [Ancestor]
    Entry 2 = A [Ours]
  Conflict two:
    Flags = HAS_THEIRS|DF_CONFLICT_CHILD
    Entry 1 = A/child [Theirs]

Thanks for your input on this.

-ed
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help