Re: [PATCH 00/48] Handling more corner cases in merge-recursive.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 3, 2011 at 6:20 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote:
> Unfortunately I seem to have found a regression that manifests in the real
> life.
>
> When this series is merged to 'next', it mismerges a trivial renamed path.

I know the problem, and can think of a couple potential solutions but
I'm not sure which one of those (if any) should be used.  I may need
advice from an unpack_trees expert.

This breakage was introduced in d487486 (merge-recursive: When we
detect we can skip an update, actually skip it 2011-06-08), and the
reason for the breakage is that was_tracked(path) is lying to us.  Let
me explain...

If you run with GIT_MERGE_VERBOSITY=3, you'll note that you get the message
  "Skipped two (merged same as existing)"
which is NOT the path it should be taking.  The reason for this is
that the call to was_tracked('two') just before that is returning true
for us when the correct answer is false.  Explaining why we get the
wrong answer requires understanding a couple things.

Using your simple reproduction recipe as an example to explain this,
the sha1sums and paths for your merge case are:
  Base commit: d00491f... one
  HEAD commit: 0cfbf08... one
  side commit: d00491f... two
In other words, 'one' is modified in HEAD, and unchanged other than
being renamed (to 'two') on side.

Now, was_tracked() simply checks whether there is a cache entry in the
current index with either stage 0 or stage 2.  Clearly, I was
expecting 'two' to only appear with stage 3, but that's not what
happened.

When unpacking these trees, we got three cache entries: one for path
'one' at stage 1, one for path 'one' at stage 2, and one for path
'two' at stage 0.  Yes, stage 0 and not stage 3.  The reason for this
is that this is case 2ALT from
Documentation/technical/trivial-merge.txt:

case  ancest    head    remote    result
----------------------------------------
...
2ALT  (empty)+  *empty* remote    remote

This means the threeway_merge code considers it a clean merge and
calls merged_entry on it, which clears the CE_STAGEMASK bits from the
cache entry flags.

Since the cache entry for path 'two' has the CE_STAGEMASK bits
cleared, when we call was_tracked on that path, we get back the answer
true.  'two' was not tracked in HEAD, though, so this is the wrong
answer and the source of the bug.


Now, the question is...how do we fix the was_tracked function?  It
would be nice to make use of the original index we had before
unpacking, but that is overwritten at the end of unpack_trees.  Should
we save it somewhere?  Or should we save off all the tracked filenames
before unpacking into a linked list and then have was_tracked() use
that instead of looking it up in the current cache? (I'm slightly
worried that may be slow given the number of lookups that exist).

Thoughts?

Elijah
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]