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

Re: Premerging topics

From
Johan Herland <johan@herland.net>
Date
Apr 24, 2013, 06:22 UTC
Message-ID
<CALKQrgd8jZQ__rnAT3wbfx-Y6mg-vrTdam53nS2ya2c=yMcS6Q@mail.gmail.com>
In-Reply-To
<7vzjwofpht.fsf@alter.siamese.dyndns.org>
On Wed, Apr 24, 2013 at 7:48 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 39 quoted lines
> Johan Herland <johan@herland.net> writes:
>
>>> But P is a commit(/merge with two parents), not a blob. Can we have trees
>>> pointing to commits instead of blobs ?
>>
>> Sort of. We do so when recording submodules in regular git trees.
>
> You are using notes to maintain reachability, aren't you?  Because
> commit objects that appears in trees are not treated as reachable
> from the trees, that won't fly.
>
> I think you guys are making it unnecessarily complex by using notes.
> To record a prepared evil merge for merging branch that contains A
> with another branch that contains B (assuming that the interation
> between A and B is what makes the evil merge necessary, e.g. A
> renames a function foo() to bar(), while B adds new callsite that
> calls foo()), we can store a single commit that records the prepared
> evil merge under "refs/merge-fix/$A-$B" where A and B are their
> object names.
>
> Then when merging a branch Y that contains B into our history X that
> already contains A (or vice versa),
>
>   ---o---o---A---o---X... ???
>       \                  .
>        \                .
>         \              .
>          o---B----o---Y
>
> we can enumerate the commits that appear in "log --left-right X...Y"
> on the left/right side and notice there is refs/merge-fix/$A-$B.
>
> So the simplest implementation of "an efficient data store to record
> a commit for <A,B> pair" turns out to be just a ref namespace ;-)
>
> There may be other <C,D> pairs in X...Y history, and it probably is
> the sane thing to do to replay prepackaged evil merges from older to
> newer in the topological sense, but that loop would be trivial, once
> we understand how to replay a single such evil merge.

This raises the same question I recently asked Antoine: For a given prepackaged merge <X,Y>, do we assume that it only resolves conflicts between the changes introduced in commit X vs. changes introduced in commit Y, or do we assume that it resolves conflicts between the histories leading up to X and Y, respectively? In other words, does <X,Y> _supercede_ earlier pre-merges between the histories leading up to X and Y?

I think the latter makes more sense, since we can then reduce the number of pre-merges to consider in the final merge. There might still be more than one pre-merge to consider, though, e.g. in criss-cross cases like this:

  ---o---o---o---o---o---o---o---o
      \             /     \       \
       \           /       \       \
        \         /         \       \
         o---o---o           P2      \
          \       \         /         \
           \       \       /           M
            \       \     /           /
             o---o---+---o           /
              \       \   \         /
               \       P1  \       /
                \     /     \     /
                 o---o---o---o---o
(there is no commit at the "+")
Show 50 quoted lines
> The actual merge-fix data should be just a commit with a single
> parent. The easiest way to prepare it would be like this:
>
>   ---o---o---A
>       \       \
>        \       M---F
>         \     /
>          o---B
>
> where M is the result of mechanical merge between A and B (there
> could be textual conflicts and you could choose to leave them in, or
> you could choose to have rerere resolve it.  As long as you do the
> same when replaying this prepackaged evil merge, this choice does
> not matter, but using rerere will make your life easier), and F is
> the final result you would want, with semantics conflicts resolved.
> In other words, in the ideal world, you would have resolved a merge
> between A and B to record the tree of F.
>
> Point "F" with refs/merge-fix/$A-$B and you are done.
>
> When you replay this prepackaged evil merge, first you mechanically
> merge X and Y without worrying about M or F to produce N.  If you
> allowed rerere to resolve textual conflicts between A and B when you
> recorded M, allow rerere to resolve this merge.  Otherwise leave the
> textual conflict in.
>
>   ---o---o---A---o---X
>       \               \
>        \               N
>         \             /
>          o---B---o---Y
>
> Then on top of N, you cherry-pick F, which will bring the semantic
> conflict resolution between M and F on top of N.
>
>   ---o---o---A---o---X
>       \               \
>        \               N---F'
>         \             /
>          o---B---o---Y
>
> Once you know the tree shape of F', then you no longer need N.  Just
> amend it away and make the tree recorded in F' the result of the
> merge between X and Y.
>
>   ---o---o---A---o---X---.
>       \                   \
>        \                  F''
>         \                /
>          o---B---o---Y--.

This is obviously a much better way to solve it. It might already be obvious, but I would suggest when making "refs/merge-fix/$A-$B" that you canonicalize the name by always choosing A and B such that A precedes B alphabetically. That way you won't have problems with both recording "refs/merge-fix/$A-$B" and "refs/merge-fix/$B-$A".

...Johan

-- Johan Herland, <johan@herland.net> www.herland.net

Previous: Junio C HamanoNext: Junio C Hamano
Message 7 of 16 in “Premerging topics (was: [RFD] annnotating a pair of commit objects?)”
  1. Antoine PelisseApr 10, 2013
  2. Antoine PelisseApr 22, 2013
  3. Johan HerlandApr 23, 2013
  4. Antoine PelisseApr 23, 2013
  5. Johan HerlandApr 23, 2013
  6. Junio C HamanoApr 24, 2013
  7. Johan HerlandApr 24, 2013
  8. Junio C HamanoApr 24, 2013
  9. Antoine PelisseApr 29, 2013
  10. Junio C HamanoApr 29, 2013
  11. Antoine PelisseApr 29, 2013
  12. Junio C HamanoApr 29, 2013
  13. Junio C HamanoApr 23, 2013
  14. Antoine PelisseApr 23, 2013
  15. Junio C HamanoApr 23, 2013
  16. Antoine PelisseApr 23, 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.