Loom merge

John Arbash Meinel john at arbash-meinel.com
Fri Feb 4 17:00:49 UTC 2011


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I've been thinking about what it should mean when merging looms, and I
was wondering what other people think.

My specific thought is that loom merge should operate on the loom
itself, step by step. Consider this example:

loom1 thread	revision
      patch-3   rev-xxx
      patch-2	rev-bbb
      patch-1	rev-aaa
      upstream	rev-1

loom2 thread	revision
      patch-3   rev-yyy
      patch-2   rev-eee
      patch-1b  rev-ddd
      patch-1   rev-ccc
      upstream	rev-2

When merging these, it would start at the bottom, and merge things in
all the way to the top. Rather than trying to do a textual merge in the
loom state file, it would instead apply 'merge --pull' sort of actions
at each thread in the loom.

So the step-by-step of merging loom2 into loom1 would be:

  1) 3-way merge the loom names, to get the proposed stack of looms. In
     this case you'll end up with:

       patch-3
       patch-2
       patch-1b
       patch-1
       upstream

     3-way merge is used so that you can handle people removing
     threads, different names for the bottom thread, etc.

  2) Start at the bottom most thread, and apply 'bzr merge --pull'

     a) for the upstream thread, this is a simple pull since rev-1 is a
        left-hand parent of rev-2.

     b) At patch-1, we also end up seeing that rev-aaa is a left-hand
        parent of rev-ccc, so again, we just pull into it.

     c) At patch-1b, we'll have added this thread. Since it has nothing
        to compare to, and the previous entries are simple pulls, we
        also just insert it directly.

     d) At patch-2, let's assume we have divergence. Where loom1 has
        modified patch-2, but so did loom2 (if only to merge up
        upstream changes.)

        This results in a merge, which may or may not conflict. If it
        doesn't conflict, we can probably just auto-commit the merge.
        (creating rev-fff)

     e) At patch-3. Assume we did a merge + commit of the previous
        level. At this point, rev-xxx could be a direct left-hand
	parent of rev-xxx. However, we need to handle the fact that we
        just created a new revision in patch-2's thread.

        i. If rev-xxx is a simple ancestor of rev-yyy, then we just
           start with rev-yyy and merge patch-2's rev-fff into it.
        ii. If not, how do we resolve it. I think we have 3 tips in
            play that we are trying to resolve, rev-xxx, rev-yyy and
            rev-fff. rev-fff is already an amalgam of rev-eee and
            rev-bbb, which means it doesn't cleanly apply to either xxx
            or yyy, since it will have a little bit of both ancestries
            in it.

            Graph wise, it looks something like (New is up):

             xxx yyy
              |   |
              |fff|
              |/ \|
             bbb eee
              |  /
              : :
              aaa

             So what do you *want* when things are done. If you assume
             that 'bzr log -n1' in a given thread, should show you how
             *that thread* evolved, rather than the logs of other
             threads, then you want to first resolve the tips of the
             existing patches, before you then bring in the lower level
             details.
             Which generates a graph like:

             zzz----.
              | \    \
             xxx yyy fff
              |   |  /|
              | .-|-'/
              |/  | /
             bbb eee
              |  /
              : :
              aaa

             or if you did it as discrete commits:

             zzz
              | \
             zzy '--.
              | \    \
             xxx yyy fff
              |   |  /|
              | .-|-'/
              |/  | /
             bbb eee
              |  /
              : :
              aaa

            However, from a conflicts standpoint, if bbb and eee
            conflict, then you'll end up resolving them to generate
            fff, and then have to resolve them *again* to generate zzy.

            So what if we did the merge as:
              start with fff, merge in xxx, resolve conflicts, merge in
              yyy, resolve conflicts. Reorder the parents to end up
              with xxx,yyy,fff, and commit.

            You get the graph you want (the left-hand ancestry of zzz
            shows you stuff that changed patch-3, rather than stuff
            that was brought in from patch-2)
            But I think you get the merge that you want (you don't have
            to repeatedly resolve conflicts from previous patches in
            patches that build on them)

Comments welcome. Merging looms definitely seems like something where a
gui wizard would come in *really* handy.

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEUEARECAAYFAk1MMMEACgkQJdeBCYSNAAMjkACeMANCXVsTV2DQAf0D555i5lY5
xIEAliwCy3v/GuJofwSdUy16djpiWIg=
=Lu9z
-----END PGP SIGNATURE-----



More information about the ubuntu-distributed-devel mailing list