Junio C Hamano [mailto:[email protected]] wrote:
> Edward Thomson <[email protected]> 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.
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
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html