unison/unison-src/transcripts/fix2004.md
2024-01-08 13:58:50 -08:00

2.3 KiB

.> builtins.merge

Here's the scenario that can produce bad empty namespace LCAs:

                              deletes of v4
j1: ... - v1 - v2 - v3 - v4 - v4a - v5 - v6 - v7
                                              /
                                  <empty> - v5a

                               adds of unrelated
j2: ... - v1 - v2 - v3 - v4 - x0 - x1 - x2 - x3
                                            /
                                <empty> - z1

So j1 and j2 have common history up through v4, then j1 deletes some definitions while j2 adds some definitions via shallow merges. These shallow merges then result in the LCA being the empty namespace rather than v4.

First, we create some common history before a fork:

.> alias.term builtin.Nat.+ a.delete1
.> alias.term builtin.Nat.* a.delete2
.> alias.term builtin.Nat.drop a.delete3
.> alias.type builtin.Nat a.Delete4

Now we fork a2 off of a. a continues on, deleting the terms it added previously and then adding one unrelated term via a merge with little history. It's this short history merge which will become a bad LCA of the empty namespace.

.> fork a a2
.> delete.term.verbose a.delete1
.> delete.term.verbose a.delete2
.> delete.term.verbose a.delete3
.> delete.type.verbose a.Delete4
.> alias.term .builtin.Float.+ newbranchA.dontDelete
.> merge newbranchA a
.a> find

Meanwhile, a2 adds some other unrelated terms, some via merging in namespaces with little history. When merging a2 back into a, the deletes from their common history should be respected.

.> alias.term builtin.Text.take a2.keep1
.> alias.term builtin.Text.take a2.keep2
.> alias.term builtin.Text.take a2.keep3
.> alias.term builtin.Text.take a2.keep4
.> alias.term builtin.Text.take a2.keep5
.> alias.term builtin.Text.take newbranchA2.keep6
.> merge newbranchA2 a2
.a2> find
.> fork a asquash
.> merge a2 a
.> squash a2 asquash

At this point, all the things that a has deleted (delete1, delete2, etc) should be deleted in both the merged and squashed results. Let's verify this:

.a> find
.asquash> find
.> view a.keep1 a.keep2 a.keep3
.> view asquash.keep1 asquash.keep2 asquash.keep3
.> view a.Delete4
.> view asquash.delete1