diff --git a/unison-cli/src/Unison/Codebase/Editor/HandleInput/Merge2.hs b/unison-cli/src/Unison/Codebase/Editor/HandleInput/Merge2.hs index d8166ae03a..6c4a374877 100644 --- a/unison-cli/src/Unison/Codebase/Editor/HandleInput/Merge2.hs +++ b/unison-cli/src/Unison/Codebase/Editor/HandleInput/Merge2.hs @@ -313,8 +313,6 @@ doMerge info = do Left _typecheckErr -> Nothing Right blob5 -> Just blob5 - let stageOneBranch = defnsAndLibdepsToBranch0 env.codebase blob3.stageOne mergedLibdeps - let parents = causals <&> \causal -> (causal.causalHash, Codebase.expectBranchForHash env.codebase causal.causalHash) @@ -326,7 +324,11 @@ doMerge info = do info.description ( HandleInput.Branch.CreateFrom'NamespaceWithParent info.alice.projectAndBranch.branch - (Branch.mergeNode stageOneBranch parents.alice parents.bob) + ( Branch.mergeNode + (defnsAndLibdepsToBranch0 env.codebase blob3.stageTwo mergedLibdeps) + parents.alice + parents.bob + ) ) info.alice.projectAndBranch.project (findTemporaryBranchName info.alice.projectAndBranch.project.projectId mergeSourceAndTarget) @@ -338,11 +340,18 @@ doMerge info = do done (Output.MergeFailure scratchFilePath mergeSourceAndTarget temporaryBranchName) Cli.runTransaction (Codebase.addDefsToCodebase env.codebase blob5.file) - let stageTwoBranch = Branch.batchUpdates (typecheckedUnisonFileToBranchAdds blob5.file) stageOneBranch Cli.updateProjectBranchRoot_ info.alice.projectAndBranch.branch info.description - (\_aliceBranch -> Branch.mergeNode stageTwoBranch parents.alice parents.bob) + ( \_aliceBranch -> + Branch.mergeNode + ( Branch.batchUpdates + (typecheckedUnisonFileToBranchAdds blob5.file) + (defnsAndLibdepsToBranch0 env.codebase blob3.stageOne mergedLibdeps) + ) + parents.alice + parents.bob + ) pure (Output.MergeSuccess mergeSourceAndTarget) Cli.respond finalOutput diff --git a/unison-core/src/Unison/Util/Defns.hs b/unison-core/src/Unison/Util/Defns.hs index e61c5ba7bb..5f56166d01 100644 --- a/unison-core/src/Unison/Util/Defns.hs +++ b/unison-core/src/Unison/Util/Defns.hs @@ -13,6 +13,7 @@ module Unison.Util.Defns zipDefns, zipDefnsWith, zipDefnsWith3, + zipDefnsWith4, ) where @@ -99,3 +100,14 @@ zipDefnsWith3 :: Defns tm4 ty4 zipDefnsWith3 f g (Defns terms1 types1) (Defns terms2 types2) (Defns terms3 types3) = Defns (f terms1 terms2 terms3) (g types1 types2 types3) + +zipDefnsWith4 :: + (tm1 -> tm2 -> tm3 -> tm4 -> tm5) -> + (ty1 -> ty2 -> ty3 -> ty4 -> ty5) -> + Defns tm1 ty1 -> + Defns tm2 ty2 -> + Defns tm3 ty3 -> + Defns tm4 ty4 -> + Defns tm5 ty5 +zipDefnsWith4 f g (Defns terms1 types1) (Defns terms2 types2) (Defns terms3 types3) (Defns terms4 types4) = + Defns (f terms1 terms2 terms3 terms4) (g types1 types2 types3 types4) diff --git a/unison-merge/src/Unison/Merge/Mergeblob3.hs b/unison-merge/src/Unison/Merge/Mergeblob3.hs index 97e11a8c08..b0c8a94f3a 100644 --- a/unison-merge/src/Unison/Merge/Mergeblob3.hs +++ b/unison-merge/src/Unison/Merge/Mergeblob3.hs @@ -17,8 +17,10 @@ import Data.Zip (unzip) import Unison.DataDeclaration (Decl) import Unison.DataDeclaration qualified as DataDeclaration import Unison.DeclNameLookup (DeclNameLookup, expectConstructorNames) +import Unison.DeclNameLookup qualified as DeclNameLookup import Unison.Merge.Mergeblob2 (Mergeblob2 (..)) import Unison.Merge.PrettyPrintEnv (makePrettyPrintEnvs) +import Unison.Merge.ThreeWay (ThreeWay) import Unison.Merge.ThreeWay qualified as ThreeWay import Unison.Merge.TwoWay (TwoWay) import Unison.Merge.TwoWay qualified as TwoWay @@ -38,7 +40,7 @@ import Unison.Term (Term) import Unison.Type (Type) import Unison.Util.BiMultimap (BiMultimap) import Unison.Util.BiMultimap qualified as BiMultimap -import Unison.Util.Defns (Defns (..), DefnsF, defnsAreEmpty, zipDefnsWith, zipDefnsWith3) +import Unison.Util.Defns (Defns (..), DefnsF, defnsAreEmpty, zipDefnsWith, zipDefnsWith3, zipDefnsWith4) import Unison.Util.Pretty (ColorText, Pretty) import Unison.Util.Pretty qualified as Pretty import Unison.Util.Relation qualified as Relation @@ -47,6 +49,7 @@ import Prelude hiding (unzip) data Mergeblob3 = Mergeblob3 { libdeps :: Names, stageOne :: DefnsF (Map Name) Referent TypeReference, + stageTwo :: DefnsF (Map Name) Referent TypeReference, uniqueTypeGuids :: Map Name Text, unparsedFile :: Pretty ColorText } @@ -64,6 +67,7 @@ makeMergeblob3 blob dependents0 libdeps authors = -- Identify the unconflicted dependents we need to pull into the Unison file (either first for typechecking, if -- there aren't conflicts, or else for manual conflict resolution without a typechecking step, if there are) + dependents :: TwoWay (DefnsF Set Name Name) dependents = filterDependents conflictsNames @@ -105,6 +109,13 @@ makeMergeblob3 blob dependents0 libdeps authors = dependents (bimap BiMultimap.range BiMultimap.range blob.defns.lca), uniqueTypeGuids = makeUniqueTypeGuids blob.hydratedDefns, + stageTwo = + makeStageTwo + blob.declNameLookups + conflictsNames + blob.unconflicts + dependents + (bimap BiMultimap.range BiMultimap.range <$> blob.defns), unparsedFile = makePrettyUnisonFile authors renderedConflicts renderedDependents } @@ -164,6 +175,41 @@ makeStageOneV :: Unconflicts v -> Set Name -> Map Name v -> Map Name v makeStageOneV unconflicts namesToDelete = (`Map.withoutKeys` namesToDelete) . Unconflicts.apply unconflicts +makeStageTwo :: + forall term typ. + TwoWay DeclNameLookup -> + TwoWay (DefnsF Set Name Name) -> + DefnsF Unconflicts term typ -> + TwoWay (DefnsF Set Name Name) -> + ThreeWay (DefnsF (Map Name) term typ) -> + DefnsF (Map Name) term typ +makeStageTwo declNameLookups conflicts unconflicts dependents defns = + zipDefnsWith4 makeStageTwoV makeStageTwoV defns.lca aliceBiasedDependents unconflicts aliceConflicts + where + aliceConflicts :: DefnsF (Map Name) term typ + aliceConflicts = + zipDefnsWith + (\defns conflicts -> Map.restrictKeys defns (conflicts <> aliceConstructorsOfTypeConflicts)) + Map.restrictKeys + defns.alice + conflicts.alice + + aliceConstructorsOfTypeConflicts :: Set Name + aliceConstructorsOfTypeConflicts = + foldMap + (Set.fromList . DeclNameLookup.expectConstructorNames declNameLookups.alice) + conflicts.alice.types + + aliceBiasedDependents :: DefnsF (Map Name) term typ + aliceBiasedDependents = + TwoWay.twoWay + (zipDefnsWith (Map.unionWith const) (Map.unionWith const)) + (zipDefnsWith Map.restrictKeys Map.restrictKeys <$> ThreeWay.forgetLca defns <*> dependents) + +makeStageTwoV :: Map Name v -> Map Name v -> Unconflicts v -> Map Name v -> Map Name v +makeStageTwoV lca dependents unconflicts conflicts = + Map.unionWith const conflicts (Unconflicts.apply unconflicts (Map.unionWith const dependents lca)) + -- Given just named term/type reference ids, fill out all names that occupy the term and type namespaces. This is simply -- the given names plus all of the types' constructors. -- diff --git a/unison-src/transcripts/merge.md b/unison-src/transcripts/merge.md index 292ccdb278..70e433d905 100644 --- a/unison-src/transcripts/merge.md +++ b/unison-src/transcripts/merge.md @@ -14,11 +14,11 @@ contains both additions. ## Basic merge: two unconflicted adds ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` Alice's adds: @@ -28,8 +28,8 @@ foo = "alices foo" ``` ```ucm:hide -project/alice> add -project/main> branch bob +scratch/alice> add +scratch/main> branch bob ``` Bob's adds: @@ -39,16 +39,16 @@ bar = "bobs bar" ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` Merge result: ```ucm -project/alice> merge /bob -project/alice> view foo bar +scratch/alice> merge /bob +scratch/alice> view foo bar ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Basic merge: two identical adds @@ -56,8 +56,8 @@ scratch/main> project.delete project If Alice and Bob also happen to add the same definition, that's not a conflict. ```ucm:hide -project/main> builtins.mergeio lib.builtins -project/main> branch alice +scratch/main> builtins.mergeio lib.builtins +scratch/main> branch alice ``` Alice's adds: @@ -67,8 +67,8 @@ foo = "alice and bobs foo" ``` ```ucm:hide -project/alice> add -project/main> branch bob +scratch/alice> add +scratch/main> branch bob ``` Bob's adds: @@ -80,16 +80,16 @@ bar : Text bar = "bobs bar" ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` Merge result: ```ucm -project/alice> merge /bob -project/alice> view foo bar +scratch/alice> merge /bob +scratch/alice> view foo bar ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Simple update propagation @@ -97,7 +97,7 @@ scratch/main> project.delete project Updates that occur in one branch are propagated to the other. In this example, Alice updates `foo`, while Bob adds a new dependent `bar` of the original `foo`. When Bob's branch is merged into Alice's, her update to `foo` is propagated to his `bar`. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -107,8 +107,8 @@ foo = "old foo" ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's updates: @@ -118,8 +118,8 @@ foo = "new foo" ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's adds: @@ -128,21 +128,21 @@ bar : Text bar = foo ++ " - " ++ foo ``` ```ucm -project/bob> display bar +scratch/bob> display bar ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` Merge result: ```ucm -project/alice> merge /bob -project/alice> view foo bar -project/alice> display bar +scratch/alice> merge /bob +scratch/alice> view foo bar +scratch/alice> display bar ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Update propagation with common dependent @@ -152,7 +152,7 @@ We classify something as an update if its "syntactic hash"—not its normal Unis Let's see an example. We have `foo`, which depends on `bar` and `baz`. Alice updates `bar` (propagating to `foo`), and Bob updates `baz` (propagating to `foo`). When we merge their updates, both updates will be reflected in the final `foo`. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -168,8 +168,8 @@ baz = "old baz" ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's updates: @@ -179,13 +179,13 @@ bar = "alices bar" ``` ```ucm:hide -project/alice> update +scratch/alice> update ``` ```ucm -project/alice> display foo +scratch/alice> display foo ``` ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` Bob's updates: @@ -195,20 +195,20 @@ baz = "bobs baz" ``` ```ucm:hide -project/bob> update +scratch/bob> update ``` ```ucm -project/bob> display foo +scratch/bob> display foo ``` Merge result: ```ucm -project/alice> merge /bob -project/alice> view foo bar baz -project/alice> display foo +scratch/alice> merge /bob +scratch/alice> view foo bar baz +scratch/alice> display foo ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Propagating an update to an update @@ -216,7 +216,7 @@ scratch/main> project.delete project Of course, it's also possible for Alice's update to propagate to one of Bob's updates. In this example, `foo` depends on `bar` which depends on `baz`. Alice updates `baz`, propagating to `bar` and `foo`, while Bob updates `bar` (to something that still depends on `foo`), propagating to `baz`. The merged result will have Alice's update to `foo` incorporated into Bob's updated `bar`, and both updates will propagate to `baz`. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -232,13 +232,13 @@ baz = "old baz" ``` ```ucm:hide -project/main> add +scratch/main> add ``` ```ucm -project/main> display foo +scratch/main> display foo ``` ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` Alice's updates: @@ -248,13 +248,13 @@ baz = "alices baz" ``` ```ucm:hide -project/alice> update +scratch/alice> update ``` ```ucm -project/alice> display foo +scratch/alice> display foo ``` ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` Bob's updates: @@ -264,21 +264,21 @@ bar = "bobs bar" ++ " - " ++ baz ``` ```ucm:hide -project/bob> update +scratch/bob> update ``` ```ucm -project/bob> display foo +scratch/bob> display foo ``` Merge result: ```ucm -project/alice> merge /bob -project/alice> view foo bar baz -project/alice> display foo +scratch/alice> merge /bob +scratch/alice> view foo bar baz +scratch/alice> display foo ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Update + delete isn't (currently) a conflict @@ -286,7 +286,7 @@ scratch/main> project.delete project We don't currently consider "update + delete" a conflict like Git does. In this situation, the delete is just ignored, allowing the update to proceed. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -296,8 +296,8 @@ foo = "old foo" ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's updates: @@ -307,23 +307,23 @@ foo = "alices foo" ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's changes: ```ucm -project/bob> delete.term foo +scratch/bob> delete.term foo ``` Merge result: ```ucm -project/alice> merge /bob -project/alice> view foo +scratch/alice> merge /bob +scratch/alice> view foo ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` In a future version, we'd like to give the user a warning at least. @@ -333,12 +333,12 @@ In a future version, we'd like to give the user a warning at least. Library dependencies don't cause merge conflicts, the library dependencies are just unioned together. If two library dependencies have the same name but different namespace hashes, then the merge algorithm makes up two fresh names. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Alice's adds: ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` ```unison:hide @@ -353,8 +353,8 @@ lib.bothDifferent.baz = 19 ``` ```ucm:hide -project/alice> add -project/main> branch bob +scratch/alice> add +scratch/main> branch bob ``` Bob's adds: @@ -370,16 +370,16 @@ lib.bothDifferent.baz = 21 ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` Merge result: ```ucm -project/alice> merge bob -project/alice> view foo bar baz +scratch/alice> merge bob +scratch/alice> view foo bar baz ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## No-op merge (Bob = Alice) @@ -387,17 +387,17 @@ scratch/main> project.delete project If Bob is equals Alice, then merging Bob into Alice looks like this. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm -project/main> branch alice -project/main> branch bob -project/alice> merge /bob +scratch/main> branch alice +scratch/main> branch bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## No-op merge (Bob < Alice) @@ -405,12 +405,12 @@ scratch/main> project.delete project If Bob is behind Alice, then merging Bob into Alice looks like this. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm -project/main> branch alice -project/main> branch bob +scratch/main> branch alice +scratch/main> branch bob ``` Alice's addition: @@ -420,12 +420,12 @@ foo = "foo" ``` ```ucm -project/alice> add -project/alice> merge /bob +scratch/alice> add +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Fast-forward merge (Bob > Alice) @@ -433,12 +433,12 @@ scratch/main> project.delete project If Bob is ahead of Alice, then merging Bob into Alice looks like this. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm -project/main> branch alice -project/main> branch bob +scratch/main> branch alice +scratch/main> branch bob ``` Bob's addition: @@ -448,23 +448,23 @@ foo = "foo" ``` ```ucm -project/bob> add -project/alice> merge /bob +scratch/bob> add +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## No-op merge: merge empty namespace into empty namespace ```ucm -project/main> branch topic -project/main> merge /topic +scratch/main> branch topic +scratch/main> merge /topic ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: someone deleted something @@ -476,7 +476,7 @@ This can cause merge failures due to out-of-scope identifiers, and the user may In this example, Alice deletes `foo`, while Bob adds a new dependent of `foo`. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -486,15 +486,15 @@ foo = "foo" ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's delete: ```ucm -project/alice> delete.term foo +scratch/alice> delete.term foo ``` ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` Bob's new code that depends on `foo`: @@ -504,12 +504,12 @@ bar = foo ++ " - " ++ foo ``` ```ucm:error -project/bob> add -project/alice> merge /bob +scratch/bob> add +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: type error @@ -519,7 +519,7 @@ It may be Alice's and Bob's changes merge together cleanly in the sense that the In this example, Alice updates a `Text` to a `Nat`, while Bob adds a new dependent of the `Text`. Upon merging, propagating Alice's update to Bob's dependent causes a typechecking failure. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -529,8 +529,8 @@ foo = "foo" ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's update: @@ -540,8 +540,8 @@ foo = 100 ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's new definition: @@ -551,15 +551,15 @@ bar = foo ++ " - " ++ foo ``` ```ucm:hide -project/bob> update +scratch/bob> update ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: simple term conflict @@ -568,7 +568,7 @@ Alice and Bob may disagree about the definition of a term. In this case, the con are presented to the user to resolve. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -581,8 +581,8 @@ bar = "old bar" ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's changes: @@ -598,8 +598,8 @@ qux = "alices qux depends on alices foo" ++ foo ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's changes: @@ -613,18 +613,18 @@ baz = "bobs baz" ``` ```ucm:hide -project/bob> update +scratch/bob> update ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm -project/merge-bob-into-alice> view bar baz +scratch/merge-bob-into-alice> view bar baz ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: simple type conflict @@ -632,7 +632,7 @@ scratch/main> project.delete project Ditto for types; if the hashes don't match, it's a conflict. In this example, Alice and Bob do different things to the same constructor. However, any explicit changes to the same type will result in a conflict, including changes that could concievably be merged (e.g. Alice and Bob both add a new constructor, or edit different constructors). ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -641,8 +641,8 @@ unique type Foo = MkFoo Nat ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's changes: @@ -651,8 +651,8 @@ unique type Foo = MkFoo Nat Nat ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's changes: @@ -660,14 +660,14 @@ Bob's changes: unique type Foo = MkFoo Nat Text ``` ```ucm:hide -project/bob> update +scratch/bob> update ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: type-update + constructor-rename conflict @@ -675,7 +675,7 @@ scratch/main> project.delete project We model the renaming of a type's constructor as an update, so if Alice updates a type and Bob renames one of its constructors (even without changing its structure), we consider it a conflict. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -684,8 +684,8 @@ unique type Foo = Baz Nat | Qux Text ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's changes `Baz Nat` to `Baz Nat Nat` @@ -694,20 +694,20 @@ unique type Foo = Baz Nat Nat | Qux Text ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's renames `Qux` to `BobQux`: ```ucm -project/bob> move.term Foo.Qux Foo.BobQux +scratch/bob> move.term Foo.Qux Foo.BobQux ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: constructor-rename conflict @@ -715,7 +715,7 @@ scratch/main> project.delete project Here is another example demonstrating that constructor renames are modeled as updates. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -724,28 +724,28 @@ unique type Foo = Baz Nat | Qux Text ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's rename: ```ucm -project/alice> move.term Foo.Baz Foo.Alice +scratch/alice> move.term Foo.Baz Foo.Alice ``` ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` Bob's rename: ```ucm -project/bob> move.term Foo.Qux Foo.Bob +scratch/bob> move.term Foo.Qux Foo.Bob ``` ```ucm:error -project/alice> merge bob +scratch/alice> merge bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: non-constructor/constructor conflict @@ -753,11 +753,11 @@ scratch/main> project.delete project A constructor on one side can conflict with a regular term definition on the other. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` Alice's additions: @@ -767,8 +767,8 @@ my.cool.thing = 17 ``` ```ucm:hide -project/alice> add -project/main> branch bob +scratch/alice> add +scratch/main> branch bob ``` Bob's additions: @@ -778,15 +778,15 @@ unique ability my.cool where ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge bob +scratch/alice> merge bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge failure: type/type conflict with term/constructor conflict @@ -794,7 +794,7 @@ scratch/main> project.delete project Here's a subtle situation where a new type is added on each side of the merge, and an existing term is replaced with a constructor of one of the types. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -804,8 +804,8 @@ Foo.Bar = 17 ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice adds this type `Foo` with constructor `Foo.Alice`: @@ -814,13 +814,13 @@ unique type Foo = Alice Nat ``` ```ucm:hide -project/alice> add -project/main> branch bob +scratch/alice> add +scratch/main> branch bob ``` Bob adds the type `Foo` with constructor `Foo.Bar`, replacing the original `Foo.Bar` term: ```ucm -project/bob> delete.term Foo.Bar +scratch/bob> delete.term Foo.Bar ``` ```unison:hide @@ -828,22 +828,22 @@ unique type Foo = Bar Nat Nat ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` These won't cleanly merge. ```ucm:error -project/alice> merge bob +scratch/alice> merge bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` Here's a more involved example that demonstrates the same idea. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` In the LCA, we have a type with two constructors, and some term. @@ -858,16 +858,16 @@ Foo.Bar.Hello = 17 ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice deletes this type entirely, and repurposes its constructor names for other terms. She also updates the term. ```ucm:hide -project/alice> delete.type Foo -project/alice> delete.term Foo.Bar.Baz -project/alice> delete.term Foo.Bar.Qux +scratch/alice> delete.type Foo +scratch/alice> delete.term Foo.Bar.Baz +scratch/alice> delete.term Foo.Bar.Qux ``` ```unison:hide:all @@ -882,23 +882,23 @@ Foo.Bar.Hello = 18 ``` ```ucm:hide -project/alice> update +scratch/alice> update ``` ```ucm -project/alice> view Foo.Bar.Baz Foo.Bar.Qux Foo.Bar.Hello +scratch/alice> view Foo.Bar.Baz Foo.Bar.Qux Foo.Bar.Hello ``` Bob, meanwhile, first deletes the term, then sort of deletes the type and re-adds it under another name, but one constructor's fully qualified names doesn't actually change. The other constructor reuses the name of the deleted term. ```ucm:hide -project/main> branch bob -project/bob> delete.term Foo.Bar.Hello -project/bob> move.type Foo Foo.Bar -project/bob> move.term Foo.Bar.Qux Foo.Bar.Hello +scratch/main> branch bob +scratch/bob> delete.term Foo.Bar.Hello +scratch/bob> move.type Foo Foo.Bar +scratch/bob> move.term Foo.Bar.Qux Foo.Bar.Hello ``` ```ucm -project/bob> view Foo.Bar +scratch/bob> view Foo.Bar ``` At this point, Bob and alice have both updated the name `Foo.Bar.Hello` in different ways, so that's a conflict. Therefore, Bob's entire type (`Foo.Bar` with constructors `Foo.Bar.Baz` and `Foo.Bar.Hello`) gets rendered into the scratch file. @@ -906,11 +906,11 @@ At this point, Bob and alice have both updated the name `Foo.Bar.Hello` in diffe Notably, Alice's "unconflicted" update on the name "Foo.Bar.Baz" (because she changed its hash and Bob didn't touch it) is nonetheless considered conflicted with Bob's "Foo.Bar.Baz". ```ucm:error -project/alice> merge bob +scratch/alice> merge bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Merge algorithm quirk: add/add unique types @@ -922,11 +922,11 @@ which is a parse error. We will resolve this situation automatically in a future version. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` Alice's additions: @@ -938,8 +938,8 @@ alice _ = 18 ``` ```ucm:hide -project/alice> add -project/main> branch bob +scratch/alice> add +scratch/main> branch bob ``` Bob's additions: @@ -951,15 +951,15 @@ bob _ = 19 ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge bob +scratch/alice> merge bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## `merge.commit` example (success) @@ -968,7 +968,7 @@ After merge conflicts are resolved, you can use `merge.commit` rather than `swit "commit" your changes. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -978,8 +978,8 @@ foo = "old foo" ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's changes: @@ -989,8 +989,8 @@ foo = "alices foo" ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's changes: @@ -1003,10 +1003,10 @@ foo = "bobs foo" Attempt to merge: ```ucm:hide -project/bob> update +scratch/bob> update ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` Resolve conflicts and commit: @@ -1017,14 +1017,14 @@ foo = "alice and bobs foo" ``` ```ucm -project/merge-bob-into-alice> update -project/merge-bob-into-alice> merge.commit -project/alice> view foo -project/alice> branches +scratch/merge-bob-into-alice> update +scratch/merge-bob-into-alice> merge.commit +scratch/alice> view foo +scratch/alice> branches ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## `merge.commit` example (failure) @@ -1032,19 +1032,19 @@ scratch/main> project.delete project `merge.commit` can only be run on a "merge branch". ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm -project/main> branch topic +scratch/main> branch topic ``` ```ucm:error -project/topic> merge.commit +scratch/topic> merge.commit ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` @@ -1057,7 +1057,7 @@ There are a number of conditions under which we can't perform a merge, and the u If `foo` and `bar` are aliases in the nearest common ancestor, but not in Alice's branch, then we don't know whether to update Bob's dependents to Alice's `foo` or Alice's `bar` (and vice-versa). ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Original branch: @@ -1070,8 +1070,8 @@ bar = 100 ``` ```ucm:hide -project/main> add -project/main> branch alice +scratch/main> add +scratch/main> branch alice ``` Alice's updates: @@ -1084,8 +1084,8 @@ bar = 300 ``` ```ucm:hide -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` Bob's addition: @@ -1095,15 +1095,15 @@ baz = "baz" ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Conflict involving builtin @@ -1114,21 +1114,21 @@ conflict involving a builtin, we can't perform a merge. One way to fix this in the future would be to introduce a syntax for defining aliases in the scratch file. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` Alice's branch: ```ucm -project/alice> alias.type lib.builtins.Nat MyNat +scratch/alice> alias.type lib.builtins.Nat MyNat ``` Bob's branch: ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` ```unison:hide @@ -1136,15 +1136,15 @@ unique type MyNat = MyNat Nat ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Constructor alias @@ -1152,11 +1152,11 @@ scratch/main> project.delete project Each naming of a decl may not have more than one name for each constructor, within the decl's namespace. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` Alice's branch: @@ -1165,15 +1165,15 @@ unique type Foo = Bar ``` ```ucm:hide -project/alice> add +scratch/alice> add ``` ```ucm -project/alice> alias.term Foo.Bar Foo.some.other.Alias +scratch/alice> alias.term Foo.Bar Foo.some.other.Alias ``` Bob's branch: ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` ```unison:hide @@ -1182,15 +1182,15 @@ bob = 100 ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Missing constructor name @@ -1198,12 +1198,12 @@ scratch/main> project.delete project Each naming of a decl must have a name for each constructor, within the decl's namespace. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Alice's branch: ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` ```unison:hide @@ -1211,16 +1211,16 @@ unique type Foo = Bar ``` ```ucm:hide -project/alice> add +scratch/alice> add ``` ```ucm -project/alice> delete.term Foo.Bar +scratch/alice> delete.term Foo.Bar ``` Bob's branch: ```ucm:hide -project/main> branch /bob +scratch/main> branch /bob ``` ```unison:hide @@ -1229,15 +1229,15 @@ bob = 100 ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Nested decl alias @@ -1245,12 +1245,12 @@ scratch/main> project.delete project A decl cannot be aliased within the namespace of another of its aliased. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Alice's branch: ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` ```unison:hide @@ -1259,16 +1259,16 @@ structural type A.inner.X = Y Nat | Z Nat Nat ``` ```ucm:hide -project/alice> add +scratch/alice> add ``` ```ucm -project/alice> names A +scratch/alice> names A ``` Bob's branch: ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` ```unison:hide @@ -1277,15 +1277,15 @@ bob = 100 ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Stray constructor alias @@ -1293,12 +1293,12 @@ scratch/main> project.delete project Constructors may only exist within the corresponding decl's namespace. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Alice's branch: ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` ```unison:hide:all @@ -1306,13 +1306,13 @@ unique type Foo = Bar ``` ```ucm -project/alice> add -project/alice> alias.term Foo.Bar AliasOutsideFooNamespace +scratch/alice> add +scratch/alice> alias.term Foo.Bar AliasOutsideFooNamespace ``` Bob's branch: ```ucm:hide -project/main> branch bob +scratch/main> branch bob ``` ```unison:hide:all @@ -1321,15 +1321,15 @@ bob = 101 ``` ```ucm -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge bob +scratch/alice> merge bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Term or type in `lib` @@ -1337,12 +1337,12 @@ scratch/main> project.delete project By convention, `lib` can only namespaces; each of these represents a library dependencies. Individual terms and types are not allowed at the top level of `lib`. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` Alice's branch: ```ucm:hide -project/main> branch alice +scratch/main> branch alice ``` ```unison:hide @@ -1351,8 +1351,8 @@ lib.foo = 1 ``` ```ucm:hide -project/alice> add -project/main> branch bob +scratch/alice> add +scratch/main> branch bob ``` Bob's branch: @@ -1362,15 +1362,15 @@ bob = 100 ``` ```ucm:hide -project/bob> add +scratch/bob> add ``` ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## LCA precondition violations @@ -1381,7 +1381,7 @@ Here's an example. We'll delete a constructor name from the LCA and still be abl together. ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` LCA: @@ -1391,16 +1391,16 @@ structural type Foo = Bar Nat | Baz Nat Nat ``` ```ucm -project/main> add -project/main> delete.term Foo.Baz +scratch/main> add +scratch/main> delete.term Foo.Baz ``` Alice's branch: ```ucm -project/main> branch alice -project/alice> delete.type Foo -project/alice> delete.term Foo.Bar +scratch/main> branch alice +scratch/alice> delete.type Foo +scratch/alice> delete.term Foo.Bar ``` ```unison @@ -1409,15 +1409,15 @@ alice = 100 ``` ```ucm -project/alice> add +scratch/alice> add ``` Bob's branch: ```ucm -project/main> branch bob -project/bob> delete.type Foo -project/bob> delete.term Foo.Bar +scratch/main> branch bob +scratch/bob> delete.type Foo +scratch/bob> delete.term Foo.Bar ``` ```unison @@ -1426,17 +1426,17 @@ bob = 101 ``` ```ucm -project/bob> add +scratch/bob> add ``` Now we merge: ```ucm -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ## Regression tests @@ -1445,7 +1445,7 @@ scratch/main> project.delete project ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```unison @@ -1454,9 +1454,9 @@ bar = 17 ``` ```ucm -project/main> add -project/main> branch alice -project/alice> delete.term bar +scratch/main> add +scratch/main> branch alice +scratch/alice> delete.term bar ``` ```unison @@ -1464,8 +1464,8 @@ foo = 18 ``` ```ucm -project/alice> update -project/main> branch bob +scratch/alice> update +scratch/main> branch bob ``` ```unison @@ -1473,22 +1473,22 @@ bob = 101 ``` ```ucm -project/bob> add +scratch/bob> add ``` ```ucm -project/alice> merge /bob +scratch/alice> merge /bob ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Delete a constructor ```ucm:hide -project/main> builtins.mergeio lib.builtins +scratch/main> builtins.mergeio lib.builtins ``` ```unison @@ -1496,8 +1496,8 @@ type Foo = Bar | Baz ``` ```ucm -project/main> add -project/main> branch topic +scratch/main> add +scratch/main> branch topic ``` ```unison @@ -1505,7 +1505,7 @@ boop = "boop" ``` ```ucm -project/topic> add +scratch/topic> add ``` ```unison @@ -1513,16 +1513,16 @@ type Foo = Bar ``` ```ucm -project/main> update +scratch/main> update ``` ```ucm -project/main> merge topic -project/main> view Foo +scratch/main> merge topic +scratch/main> view Foo ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Dependent that doesn't need to be in the file @@ -1531,7 +1531,7 @@ This test demonstrates a bug. ```ucm:hide -project/alice> builtins.mergeio lib.builtins +scratch/alice> builtins.mergeio lib.builtins ``` In the LCA, we have `foo` with dependent `bar`, and `baz`. @@ -1548,8 +1548,8 @@ baz = "lca" ``` ```ucm -project/alice> add -project/alice> branch bob +scratch/alice> add +scratch/alice> branch bob ``` On Bob, we update `baz` to "bob". @@ -1560,7 +1560,7 @@ baz = "bob" ``` ```ucm -project/bob> update +scratch/bob> update ``` On Alice, we update `baz` to "alice" (conflict), but also update `foo` (unconflicted), which propagates to `bar`. @@ -1574,20 +1574,20 @@ baz = "alice" ``` ```ucm -project/alice> update +scratch/alice> update ``` When we try to merge Bob into Alice, we should see both versions of `baz`, with Alice's unconflicted `foo` and `bar` in the underlying namespace. ```ucm:error -project/alice> merge /bob +scratch/alice> merge /bob ``` But `bar` was put into the scratch file instead. ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Merge loop test @@ -1602,7 +1602,7 @@ a = 1 ``` ```ucm -project/alice> add +scratch/alice> add ``` ```unison @@ -1610,7 +1610,7 @@ b = 2 ``` ```ucm -project/alice> add +scratch/alice> add ``` ```unison @@ -1618,7 +1618,7 @@ b = 2 ``` ```ucm -project/bob> add +scratch/bob> add ``` ```unison @@ -1626,7 +1626,7 @@ a = 1 ``` ```ucm -project/bob> add +scratch/bob> add ``` ```unison @@ -1635,14 +1635,14 @@ b = 2 ``` ```ucm -project/carol> add -project/bob> merge /alice -project/carol> merge /bob -project/carol> history +scratch/carol> add +scratch/bob> merge /alice +scratch/carol> merge /bob +scratch/carol> history ``` ```ucm:hide -scratch/main> project.delete project +scratch/main> project.delete scratch ``` ### Variables named `_` @@ -1698,3 +1698,52 @@ scratch/alice> update ```ucm scratch/alice> merge /bob ``` + +```ucm:hide +scratch/main> project.delete scratch +``` + +### Unique type GUID reuse + +Previously, a merge branch would not include any dependents in the namespace, but that resulted in dependent unique +types' GUIDs being regenerated. + +```ucm:hide +scratch/main> builtins.mergeio lib.builtins +``` + +```unison +type Foo = Lca +type Bar = MkBar Foo +``` + +```ucm +scratch/main> add +scratch/main> branch alice +scratch/alice> move.term Foo.Lca Foo.Alice +scratch/main> branch bob +scratch/bob> move.term Foo.Lca Foo.Bob +``` + +```ucm:error +scratch/alice> merge /bob +``` + +```ucm +scratch/merge-bob-into-alice> +``` + +```unison +type Foo = Merged +type Bar = MkBar Foo +``` + +```ucm +scratch/merge-bob-into-alice> update +scratch/merge-bob-into-alice> names Bar +scratch/alice> names Bar +``` + +```ucm:hide +scratch/main> project.delete scratch +``` diff --git a/unison-src/transcripts/merge.output.md b/unison-src/transcripts/merge.output.md index 9dea5fdcf6..1e14583e44 100644 --- a/unison-src/transcripts/merge.output.md +++ b/unison-src/transcripts/merge.output.md @@ -46,11 +46,11 @@ bar = "bobs bar" Merge result: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. -project/alice> view foo bar +scratch/alice> view foo bar bar : Text bar = "bobs bar" @@ -83,11 +83,11 @@ bar = "bobs bar" Merge result: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. -project/alice> view foo bar +scratch/alice> view foo bar bar : Text bar = "bobs bar" @@ -122,7 +122,7 @@ bar = foo ++ " - " ++ foo ``` ``` ucm -project/bob> display bar +scratch/bob> display bar "old foo - old foo" @@ -130,11 +130,11 @@ project/bob> display bar Merge result: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. -project/alice> view foo bar +scratch/alice> view foo bar bar : Text bar = @@ -144,7 +144,7 @@ project/alice> view foo bar foo : Text foo = "new foo" -project/alice> display bar +scratch/alice> display bar "old foo - old foo" @@ -176,7 +176,7 @@ bar = "alices bar" ``` ``` ucm -project/alice> display foo +scratch/alice> display foo "foo - alices bar - old baz" @@ -189,7 +189,7 @@ baz = "bobs baz" ``` ``` ucm -project/bob> display foo +scratch/bob> display foo "foo - old bar - bobs baz" @@ -197,11 +197,11 @@ project/bob> display foo Merge result: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. -project/alice> view foo bar baz +scratch/alice> view foo bar baz bar : Text bar = "alices bar" @@ -214,7 +214,7 @@ project/alice> view foo bar baz use Text ++ "foo" ++ " - " ++ bar ++ " - " ++ baz -project/alice> display foo +scratch/alice> display foo "foo - alices bar - bobs baz" @@ -237,7 +237,7 @@ baz = "old baz" ``` ``` ucm -project/main> display foo +scratch/main> display foo "old foo - old bar - old baz" @@ -250,7 +250,7 @@ baz = "alices baz" ``` ``` ucm -project/alice> display foo +scratch/alice> display foo "old foo - old bar - alices baz" @@ -263,7 +263,7 @@ bar = "bobs bar" ++ " - " ++ baz ``` ``` ucm -project/bob> display foo +scratch/bob> display foo "old foo - bobs bar - old baz" @@ -271,11 +271,11 @@ project/bob> display foo Merge result: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. -project/alice> view foo bar baz +scratch/alice> view foo bar baz bar : Text bar = @@ -290,7 +290,7 @@ project/alice> view foo bar baz use Text ++ "old foo" ++ " - " ++ bar -project/alice> display foo +scratch/alice> display foo "old foo - bobs bar - alices baz" @@ -316,7 +316,7 @@ foo = "alices foo" Bob's changes: ``` ucm -project/bob> delete.term foo +scratch/bob> delete.term foo Done. @@ -324,11 +324,11 @@ project/bob> delete.term foo Merge result: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. -project/alice> view foo +scratch/alice> view foo foo : Text foo = "alices foo" @@ -369,11 +369,11 @@ lib.bothDifferent.baz = 21 Merge result: ``` ucm -project/alice> merge bob +scratch/alice> merge bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. -project/alice> view foo bar baz +scratch/alice> view foo bar baz lib.alice.foo : Nat lib.alice.foo = 17 @@ -396,25 +396,25 @@ project/alice> view foo bar baz If Bob is equals Alice, then merging Bob into Alice looks like this. ``` ucm -project/main> branch alice +scratch/main> branch alice Done. I've created the alice branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /alice`. -project/main> branch bob +scratch/main> branch bob Done. I've created the bob branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /bob`. -project/alice> merge /bob +scratch/alice> merge /bob 😶 - project/alice was already up-to-date with project/bob. + scratch/alice was already up-to-date with scratch/bob. ``` ## No-op merge (Bob \< Alice) @@ -422,14 +422,14 @@ project/alice> merge /bob If Bob is behind Alice, then merging Bob into Alice looks like this. ``` ucm -project/main> branch alice +scratch/main> branch alice Done. I've created the alice branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /alice`. -project/main> branch bob +scratch/main> branch bob Done. I've created the bob branch based off of main. @@ -445,17 +445,17 @@ foo = "foo" ``` ``` ucm -project/alice> add +scratch/alice> add ⍟ I've added these definitions: foo : Text -project/alice> merge /bob +scratch/alice> merge /bob 😶 - project/alice was already up-to-date with project/bob. + scratch/alice was already up-to-date with scratch/bob. ``` ## Fast-forward merge (Bob \> Alice) @@ -463,14 +463,14 @@ project/alice> merge /bob If Bob is ahead of Alice, then merging Bob into Alice looks like this. ``` ucm -project/main> branch alice +scratch/main> branch alice Done. I've created the alice branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /alice`. -project/main> branch bob +scratch/main> branch bob Done. I've created the bob branch based off of main. @@ -486,32 +486,32 @@ foo = "foo" ``` ``` ucm -project/bob> add +scratch/bob> add ⍟ I've added these definitions: foo : Text -project/alice> merge /bob +scratch/alice> merge /bob - I fast-forward merged project/bob into project/alice. + I fast-forward merged scratch/bob into scratch/alice. ``` ## No-op merge: merge empty namespace into empty namespace ``` ucm -project/main> branch topic +scratch/main> branch topic Done. I've created the topic branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /topic`. -project/main> merge /topic +scratch/main> merge /topic 😶 - project/main was already up-to-date with project/topic. + scratch/main was already up-to-date with scratch/topic. ``` ## Merge failure: someone deleted something @@ -532,7 +532,7 @@ foo = "foo" Alice's delete: ``` ucm -project/alice> delete.term foo +scratch/alice> delete.term foo Done. @@ -545,15 +545,15 @@ bar = foo ++ " - " ++ foo ``` ``` ucm -project/bob> add +scratch/bob> add ⍟ I've added these definitions: bar : Text -project/alice> merge /bob +scratch/alice> merge /bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -606,9 +606,9 @@ bar = foo ++ " - " ++ foo ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -672,9 +672,9 @@ baz = "bobs baz" ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -692,11 +692,11 @@ project/alice> merge /bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice foo : Text foo = "alices foo" --- project/bob +-- scratch/bob foo : Text foo = "bobs foo" @@ -711,7 +711,7 @@ qux = ``` ``` ucm -project/merge-bob-into-alice> view bar baz +scratch/merge-bob-into-alice> view bar baz bar : Text bar = "alices bar" @@ -743,9 +743,9 @@ unique type Foo = MkFoo Nat Text ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -763,10 +763,10 @@ project/alice> merge /bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice type Foo = MkFoo Nat Nat --- project/bob +-- scratch/bob type Foo = MkFoo Nat Text ``` @@ -790,15 +790,15 @@ unique type Foo = Baz Nat Nat | Qux Text Bob's renames `Qux` to `BobQux`: ``` ucm -project/bob> move.term Foo.Qux Foo.BobQux +scratch/bob> move.term Foo.Qux Foo.BobQux Done. ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -816,10 +816,10 @@ project/alice> merge /bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice type Foo = Baz Nat Nat | Qux Text --- project/bob +-- scratch/bob type Foo = BobQux Text | Baz Nat ``` @@ -837,7 +837,7 @@ unique type Foo = Baz Nat | Qux Text Alice's rename: ``` ucm -project/alice> move.term Foo.Baz Foo.Alice +scratch/alice> move.term Foo.Baz Foo.Alice Done. @@ -845,15 +845,15 @@ project/alice> move.term Foo.Baz Foo.Alice Bob's rename: ``` ucm -project/bob> move.term Foo.Qux Foo.Bob +scratch/bob> move.term Foo.Qux Foo.Bob Done. ``` ``` ucm -project/alice> merge bob +scratch/alice> merge bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -871,10 +871,10 @@ project/alice> merge bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice type Foo = Qux Text | Alice Nat --- project/bob +-- scratch/bob type Foo = Bob Text | Baz Nat ``` @@ -898,9 +898,9 @@ unique ability my.cool where ``` ``` ucm -project/alice> merge bob +scratch/alice> merge bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -918,11 +918,11 @@ project/alice> merge bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice my.cool.thing : Nat my.cool.thing = 17 --- project/bob +-- scratch/bob ability my.cool where thing : Nat ->{cool} Nat ``` @@ -947,7 +947,7 @@ unique type Foo = Alice Nat Bob adds the type `Foo` with constructor `Foo.Bar`, replacing the original `Foo.Bar` term: ``` ucm -project/bob> delete.term Foo.Bar +scratch/bob> delete.term Foo.Bar Done. @@ -959,9 +959,9 @@ unique type Foo = Bar Nat Nat These won't cleanly merge. ``` ucm -project/alice> merge bob +scratch/alice> merge bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -979,14 +979,14 @@ project/alice> merge bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice Foo.Bar : Nat Foo.Bar = 17 --- project/alice +-- scratch/alice type Foo = Alice Nat --- project/bob +-- scratch/bob type Foo = Bar Nat Nat ``` @@ -1007,7 +1007,7 @@ Foo.Bar.Hello = 17 Alice deletes this type entirely, and repurposes its constructor names for other terms. She also updates the term. ``` ucm -project/alice> view Foo.Bar.Baz Foo.Bar.Qux Foo.Bar.Hello +scratch/alice> view Foo.Bar.Baz Foo.Bar.Qux Foo.Bar.Hello Foo.Bar.Baz : Nat Foo.Bar.Baz = 100 @@ -1022,7 +1022,7 @@ project/alice> view Foo.Bar.Baz Foo.Bar.Qux Foo.Bar.Hello Bob, meanwhile, first deletes the term, then sort of deletes the type and re-adds it under another name, but one constructor's fully qualified names doesn't actually change. The other constructor reuses the name of the deleted term. ``` ucm -project/bob> view Foo.Bar +scratch/bob> view Foo.Bar type Foo.Bar = Baz Nat | Hello Nat Nat @@ -1032,9 +1032,9 @@ At this point, Bob and alice have both updated the name `Foo.Bar.Hello` in diffe Notably, Alice's "unconflicted" update on the name "Foo.Bar.Baz" (because she changed its hash and Bob didn't touch it) is nonetheless considered conflicted with Bob's "Foo.Bar.Baz". ``` ucm -project/alice> merge bob +scratch/alice> merge bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -1052,15 +1052,15 @@ project/alice> merge bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice Foo.Bar.Baz : Nat Foo.Bar.Baz = 100 --- project/alice +-- scratch/alice Foo.Bar.Hello : Nat Foo.Bar.Hello = 18 --- project/bob +-- scratch/bob type Foo.Bar = Baz Nat | Hello Nat Nat ``` @@ -1092,9 +1092,9 @@ bob _ = 19 ``` ``` ucm -project/alice> merge bob +scratch/alice> merge bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -1112,11 +1112,11 @@ project/alice> merge bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice type Foo = Bar --- project/bob +-- scratch/bob type Foo = Bar @@ -1160,9 +1160,9 @@ foo = "bobs foo" Attempt to merge: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -1180,11 +1180,11 @@ project/alice> merge /bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice foo : Text foo = "alices foo" --- project/bob +-- scratch/bob foo : Text foo = "bobs foo" @@ -1205,30 +1205,31 @@ foo = "alice and bobs foo" do an `add` or `update`, here's how your codebase would change: - ⍟ These new definitions are ok to `add`: + ⍟ These names already exist. You can `update` them to your + new definition: foo : Text ``` ``` ucm -project/merge-bob-into-alice> update +scratch/merge-bob-into-alice> update Okay, I'm searching the branch for code that needs to be updated... Done. -project/merge-bob-into-alice> merge.commit +scratch/merge-bob-into-alice> merge.commit - I fast-forward merged project/merge-bob-into-alice into - project/alice. + I fast-forward merged scratch/merge-bob-into-alice into + scratch/alice. -project/alice> view foo +scratch/alice> view foo foo : Text foo = "alice and bobs foo" -project/alice> branches +scratch/alice> branches Branch Remote branch 1. alice @@ -1241,7 +1242,7 @@ project/alice> branches `merge.commit` can only be run on a "merge branch". ``` ucm -project/main> branch topic +scratch/main> branch topic Done. I've created the topic branch based off of main. @@ -1250,7 +1251,7 @@ project/main> branch topic ``` ``` ucm -project/topic> merge.commit +scratch/topic> merge.commit It doesn't look like there's a merge in progress. @@ -1291,16 +1292,16 @@ baz = "baz" ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob Sorry, I wasn't able to perform the merge: On the merge ancestor, bar and foo were aliases for the same - term, but on project/alice the names have different + term, but on scratch/alice the names have different definitions currently. I'd need just a single new definition to use in their dependents when I merge. - Please fix up project/alice to resolve this. For example, + Please fix up scratch/alice to resolve this. For example, * `update` the definitions to be the same again, so that there's nothing for me to decide. @@ -1321,7 +1322,7 @@ One way to fix this in the future would be to introduce a syntax for defining al Alice's branch: ``` ucm -project/alice> alias.type lib.builtins.Nat MyNat +scratch/alice> alias.type lib.builtins.Nat MyNat Done. @@ -1333,7 +1334,7 @@ unique type MyNat = MyNat Nat ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob Sorry, I wasn't able to perform the merge: @@ -1357,7 +1358,7 @@ unique type Foo = Bar ``` ``` ucm -project/alice> alias.term Foo.Bar Foo.some.other.Alias +scratch/alice> alias.term Foo.Bar Foo.some.other.Alias Done. @@ -1370,11 +1371,11 @@ bob = 100 ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob Sorry, I wasn't able to perform the merge: - On project/alice, the type Foo has a constructor with multiple + On scratch/alice, the type Foo has a constructor with multiple names, and I can't perform a merge in this situation: * Foo.Bar @@ -1395,7 +1396,7 @@ unique type Foo = Bar ``` ``` ucm -project/alice> delete.term Foo.Bar +scratch/alice> delete.term Foo.Bar Done. @@ -1408,11 +1409,11 @@ bob = 100 ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob Sorry, I wasn't able to perform the merge: - On project/alice, the type Foo has some constructors with + On scratch/alice, the type Foo has some constructors with missing names, and I can't perform a merge in this situation. You can use `view Foo` and @@ -1432,7 +1433,7 @@ structural type A.inner.X = Y Nat | Z Nat Nat ``` ``` ucm -project/alice> names A +scratch/alice> names A Type Hash: #65mdg7015r @@ -1447,9 +1448,9 @@ bob = 100 ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - On project/alice, the type A.inner.X is an alias of A. I'm not + On scratch/alice, the type A.inner.X is an alias of A. I'm not able to perform a merge when a type exists nested under an alias of itself. Please separate them or delete one copy, and then try merging again. @@ -1462,13 +1463,13 @@ Constructors may only exist within the corresponding decl's namespace. Alice's branch: ``` ucm -project/alice> add +scratch/alice> add ⍟ I've added these definitions: type Foo -project/alice> alias.term Foo.Bar AliasOutsideFooNamespace +scratch/alice> alias.term Foo.Bar AliasOutsideFooNamespace Done. @@ -1476,7 +1477,7 @@ project/alice> alias.term Foo.Bar AliasOutsideFooNamespace Bob's branch: ``` ucm -project/bob> add +scratch/bob> add ⍟ I've added these definitions: @@ -1484,13 +1485,13 @@ project/bob> add ``` ``` ucm -project/alice> merge bob +scratch/alice> merge bob Sorry, I wasn't able to perform the merge, because I need all constructor names to be nested somewhere beneath the corresponding type name. - On project/alice, the constructor AliasOutsideFooNamespace is + On scratch/alice, the constructor AliasOutsideFooNamespace is not nested beneath the corresponding type name. Please either use `move` to move it, or if it's an extra copy, you can simply `delete` it. Then try the merge again. @@ -1515,11 +1516,11 @@ bob = 100 ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob Sorry, I wasn't able to perform the merge: - On project/alice, there's a type or term at the top level of + On scratch/alice, there's a type or term at the top level of the `lib` namespace, where I only expect to find subnamespaces representing library dependencies. @@ -1553,13 +1554,13 @@ structural type Foo = Bar Nat | Baz Nat Nat ``` ``` ucm -project/main> add +scratch/main> add ⍟ I've added these definitions: structural type Foo -project/main> delete.term Foo.Baz +scratch/main> delete.term Foo.Baz Done. @@ -1567,18 +1568,18 @@ project/main> delete.term Foo.Baz Alice's branch: ``` ucm -project/main> branch alice +scratch/main> branch alice Done. I've created the alice branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /alice`. -project/alice> delete.type Foo +scratch/alice> delete.type Foo Done. -project/alice> delete.term Foo.Bar +scratch/alice> delete.term Foo.Bar Done. @@ -1602,7 +1603,7 @@ alice = 100 ``` ``` ucm -project/alice> add +scratch/alice> add ⍟ I've added these definitions: @@ -1612,18 +1613,18 @@ project/alice> add Bob's branch: ``` ucm -project/main> branch bob +scratch/main> branch bob Done. I've created the bob branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /bob`. -project/bob> delete.type Foo +scratch/bob> delete.type Foo Done. -project/bob> delete.term Foo.Bar +scratch/bob> delete.term Foo.Bar Done. @@ -1647,7 +1648,7 @@ bob = 101 ``` ``` ucm -project/bob> add +scratch/bob> add ⍟ I've added these definitions: @@ -1657,9 +1658,9 @@ project/bob> add Now we merge: ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. ``` ## Regression tests @@ -1686,21 +1687,21 @@ bar = 17 ``` ``` ucm -project/main> add +scratch/main> add ⍟ I've added these definitions: bar : Nat foo : Nat -project/main> branch alice +scratch/main> branch alice Done. I've created the alice branch based off of main. Tip: To merge your work back into the main branch, first `switch /main` then `merge /alice`. -project/alice> delete.term bar +scratch/alice> delete.term bar Done. @@ -1724,14 +1725,14 @@ foo = 18 ``` ``` ucm -project/alice> update +scratch/alice> update Okay, I'm searching the branch for code that needs to be updated... Done. -project/main> branch bob +scratch/main> branch bob Done. I've created the bob branch based off of main. @@ -1757,7 +1758,7 @@ bob = 101 ``` ``` ucm -project/bob> add +scratch/bob> add ⍟ I've added these definitions: @@ -1765,9 +1766,9 @@ project/bob> add ``` ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I merged project/bob into project/alice. + I merged scratch/bob into scratch/alice. ``` ### Delete a constructor @@ -1790,13 +1791,13 @@ type Foo = Bar | Baz ``` ``` ucm -project/main> add +scratch/main> add ⍟ I've added these definitions: type Foo -project/main> branch topic +scratch/main> branch topic Done. I've created the topic branch based off of main. @@ -1822,7 +1823,7 @@ boop = "boop" ``` ``` ucm -project/topic> add +scratch/topic> add ⍟ I've added these definitions: @@ -1848,7 +1849,7 @@ type Foo = Bar ``` ``` ucm -project/main> update +scratch/main> update Okay, I'm searching the branch for code that needs to be updated... @@ -1857,11 +1858,11 @@ project/main> update ``` ``` ucm -project/main> merge topic +scratch/main> merge topic - I merged project/topic into project/main. + I merged scratch/topic into scratch/main. -project/main> view Foo +scratch/main> view Foo type Foo = Bar @@ -1899,7 +1900,7 @@ baz = "lca" ``` ``` ucm -project/alice> add +scratch/alice> add ⍟ I've added these definitions: @@ -1907,7 +1908,7 @@ project/alice> add baz : Text foo : Nat -project/alice> branch bob +scratch/alice> branch bob Done. I've created the bob branch based off of alice. @@ -1937,7 +1938,7 @@ baz = "bob" ``` ``` ucm -project/bob> update +scratch/bob> update Okay, I'm searching the branch for code that needs to be updated... @@ -1971,7 +1972,7 @@ baz = "alice" ``` ``` ucm -project/alice> update +scratch/alice> update Okay, I'm searching the branch for code that needs to be updated... @@ -1987,9 +1988,9 @@ When we try to merge Bob into Alice, we should see both versions of `baz`, with the underlying namespace. ``` ucm -project/alice> merge /bob +scratch/alice> merge /bob - I couldn't automatically merge project/bob into project/alice. + I couldn't automatically merge scratch/bob into scratch/alice. However, I've added the definitions that need attention to the top of scratch.u. @@ -2007,11 +2008,11 @@ project/alice> merge /bob ``` ``` unison:added-by-ucm scratch.u --- project/alice +-- scratch/alice baz : Text baz = "alice" --- project/bob +-- scratch/bob baz : Text baz = "bob" @@ -2052,7 +2053,7 @@ a = 1 ``` ``` ucm -project/alice> add +scratch/alice> add ⍟ I've added these definitions: @@ -2077,7 +2078,7 @@ b = 2 ``` ``` ucm -project/alice> add +scratch/alice> add ⍟ I've added these definitions: @@ -2097,7 +2098,7 @@ b = 2 ``` ``` ucm -project/bob> add +scratch/bob> add ⍟ I've added these definitions: @@ -2122,7 +2123,7 @@ a = 1 ``` ``` ucm -project/bob> add +scratch/bob> add ⍟ I've added these definitions: @@ -2143,22 +2144,22 @@ b = 2 ``` ``` ucm -project/carol> add +scratch/carol> add ⍟ I've added these definitions: a : ##Nat b : ##Nat -project/bob> merge /alice +scratch/bob> merge /alice - I merged project/alice into project/bob. + I merged scratch/alice into scratch/bob. -project/carol> merge /bob +scratch/carol> merge /bob - I merged project/bob into project/carol. + I merged scratch/bob into scratch/carol. -project/carol> history +scratch/carol> history Note: The most recent namespace hash is immediately below this message. @@ -2296,3 +2297,131 @@ scratch/alice> merge /bob I merged scratch/bob into scratch/alice. ``` +### Unique type GUID reuse + +Previously, a merge branch would not include any dependents in the namespace, but that resulted in dependent unique +types' GUIDs being regenerated. + +``` unison +type Foo = Lca +type Bar = MkBar Foo +``` + +``` ucm + + Loading changes detected in scratch.u. + + I found and typechecked these definitions in scratch.u. If you + do an `add` or `update`, here's how your codebase would + change: + + ⍟ These new definitions are ok to `add`: + + type Bar + type Foo + +``` +``` ucm +scratch/main> add + + ⍟ I've added these definitions: + + type Bar + type Foo + +scratch/main> branch alice + + Done. I've created the alice branch based off of main. + + Tip: To merge your work back into the main branch, first + `switch /main` then `merge /alice`. + +scratch/alice> move.term Foo.Lca Foo.Alice + + Done. + +scratch/main> branch bob + + Done. I've created the bob branch based off of main. + + Tip: To merge your work back into the main branch, first + `switch /main` then `merge /bob`. + +scratch/bob> move.term Foo.Lca Foo.Bob + + Done. + +``` +``` ucm +scratch/alice> merge /bob + + I couldn't automatically merge scratch/bob into scratch/alice. + However, I've added the definitions that need attention to the + top of scratch.u. + + When you're done, you can run + + merge.commit + + to merge your changes back into alice and delete the temporary + branch. Or, if you decide to cancel the merge instead, you can + run + + delete.branch /merge-bob-into-alice + + to delete the temporary branch and switch back to alice. + +``` +``` unison:added-by-ucm scratch.u +-- scratch/alice +type Foo + = Alice + +-- scratch/bob +type Foo + = Bob + +-- The definitions below are not conflicted, but they each depend on one or more +-- conflicted definitions above. + +type Bar + = MkBar Foo + +``` + +``` ucm +``` +``` unison +type Foo = Merged +type Bar = MkBar Foo +``` + +``` ucm + + Loading changes detected in scratch.u. + + I found and typechecked the definitions in scratch.u. This + file has been previously added to the codebase. + +``` +``` ucm +scratch/merge-bob-into-alice> update + + Okay, I'm searching the branch for code that needs to be + updated... + + Done. + +scratch/merge-bob-into-alice> names Bar + + Type + Hash: #h3af39sae7 + Names: Bar + +scratch/alice> names Bar + + Type + Hash: #h3af39sae7 + Names: Bar + +```