Re: Rename conflicts in the index

2 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:32

Edward Thomson [off-list ref] writes:
Junio C Hamano [mailto:gitster@pobox.com] wrote:
quoted
Edward Thomson [off-list ref] writes:
quoted
I would propose that this not simply track rename conflicts, but all
conflicts.
That is a no starter.
So.  Can you explain to me why this would be a non starter?
At least two, IIRC.  One is the consequence of the other.

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.

When a path originally at A is moved to B on only one branch, and
there are content-level conflicts between the changes made by one
branch (while going from A to B) and by the other branch (while
keeping it at A), we would end up having three stages for path B
without any trace of path A.  I do not offhand know how much it
helps to learn A in such a situation in the real life, but we are
indeed losing information, and I do not have any problem with an
extension that records in the index the fact that in the two (of the
three) commits involved in the merge, the path was at A.

But people have been successfully using existing versions of Git
without that information to merge branches with renames, and
resolving the content-level conflicts.  Your tool that
_additionally_ records "This path that currently has three stages
for B was at A in the common ancestor (i.e. stage #1) and that
branch (either stage #2 or stage #3)" does not _have_ _to_ break
these users by removing the three stages for B from the main index.

Also we do not duplicate information unnecessarily.  Nowhere in the
above "we have been losing the fact that two of the three had the
contents we have at path B in the resulting unmerged index at path
A, and that information might be useful as well", there is a reason
to write another copy of mode or SHA-1 for any of the three variants.

As I said, you do not live in the world where you are writing
something like Git from scratch.  Perhaps you do, but then the
result will not be Git and we wouldn't be discussing that system on
this mailing list.

RE: Rename conflicts in the index

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

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.
When a path originally at A is moved to B on only one branch, and there are
content-level conflicts between the changes made by one branch (while going
from A to B) and by the other branch (while keeping it at A), we would end up
having three stages for path B without any trace of path A.  I do not offhand
know how much it helps to learn A in such a situation in the real life, but we are
indeed losing information, and I do not have any problem with an extension that
records in the index the fact that in the two (of the
three) commits involved in the merge, the path was at A.
What you've described is true only for a certain class of rename conflicts,
for example the rename/edit conflict you've described above.

It's also true if you were to rename some item 'a' to 'b' in both branches.
But when 'b' is sufficiently dissimilar to become a rewrite, then I end up
with a rename of a->b on one side and deleting a and adding b on the other.
The result is a mysterious "added by us" conflict:

100644 e2dd530c9f31550a2b0c90773ccde056929d6d66 2       b

Worse yet is if I don't do the rename in my side, but I just add a new b so
that in theirs I've renamed a to b and in mine I have both a and b.  When I
do the merge, I'm told I have conflicts, except that I don't:

100644 08d4f831774aed5d4c6cb496affefd4020dce40c 0       b

The other branch's b is long gone and exists only as a dirty file in the
workdir.
But people have been successfully using existing versions of Git without that
information to merge branches with renames, and resolving the content-level
conflicts.
But you aren't afforded the option to resolve content-level conflicts if you
don't know where the conflict came from.  For example, in a rename 1->2
conflict, we dutifully detect that a was renamed to both b and c and fail,
but that fact is never given to the index.  This conflict could be fed into
a merge tool or, better, automerged, with the user only needing to pick a
path:

100644 421c9102b8562ad227ba773ab1cf6bbed7b7496d 1       a
100644 421c9102b8562ad227ba773ab1cf6bbed7b7496d 3       b
100644 421c9102b8562ad227ba773ab1cf6bbed7b7496d 2       c

I hate to sound like a broken record here, but without some more data in the
index - anywhere, really - any tool that doesn't have the luxury of emitting
data about what happened to stdout certainly can't infer anything about what
happened in the merge.

-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