🗄 Unison projects introduction

A Unison project is a Unison codebase concept that represents a library, application, or other code package that can be shared, collaborated on, and versioned. You'll create and manipulate projects with a few simple UCM commands and can view your projects on Unison Share.

One Unison codebase often houses multiple libraries, applications, works in progress, and prototypes with varying needs for sharing and structure. Given that Unison code isn't stored in files that can be grouped into git repositories or other conventional collaboration mechanisms, we knew we needed an additional codebase abstraction for a packageable unit of code. This is where Unison projects come in. Namespaces are for organizing your source code into a logical tree, whereas projects power developer workflows that are related to collaboration and dependency management.

Some things that you'll end up doing with projects include:

  • Specifying if a package is public or private
  • Working on a branch of a project without affecting the mainline
  • Creating a pull request that can be reviewed and merged by others
  • Adding a dependency on a library
  • Releasing a new version of a library

🏁 Projects quickstart

Let's walk through a quick example of how to navigate a Unison codebase with projects. We'll create a new project, add a project library dependency, create and merge a branch in our project, and push it to Unison Share.

If you've authored Unison libraries that are currently hosted on Unison share and want the 5 minute cheat-sheet for migrating your library,see the quick migration guide here.

Unison projects formalize many of the conventions you may be familiar with if you've been creating top-level namespaces for your libraries. Projects will live at the root of your codebase and dependencies will still be stored in alibdirectory for the project.

Let's create a new project calledhelloProjectsnow:

.> project.create helloProjects

  🎉 I've created the project helloProjects.

  I'll now fetch the latest version of the base Unison library...


In the UCM, your console prompt will be updated to indicate that you're in thehelloProjectsproject; the segment prefixed by a slash,/main,is abranchof the project. Branches are a new feature to Unison projects that allow for concurrent work streams, long-lived feature work, PR's, and more.

Let's create a new branch instead of working onmaindirectly.

helloProjects/main> branch myNewBranch

  Done. I've created the myNewBranch branch based off of main

  Tip: Use `merge /myNewBranch /main` to merge your work back
       into the main branch.

branchcreates a new branch of the project from the current branch. In this casemyNewBranchis a copy ofmainand contains all the same code and history. Take a look around at the branches of the current project with thebranchescommand and we should see bothmainandmyNewBranch.

helloProjects/myNewBranch> branches

       Branch        Remote branch
  1.   main
  2.   myNewBranch

Upon creating a new project, the UCM installs thebasestandard library as a dependency in thelibnamespace for you. The UCM looks for project dependencies in alibnamespace located at the root of the project. Let's add another dependency onthe distributed projectwith thepullcommand.

If you're ever wondering what thepullcommand looks like for a given project, the Unison Share UI shows you the latest download command when you navigate to the project's home page.

helloProjects/myNewBranch> pull @unison/distributed/releases/X.Y.Z lib.distributed

This will pull the given released version of thedistributedproject into thelibdirectory of the current project. We know that we are pulling a project instead of a namespace because of the @ symbol and slashes in the path. The old command for pulling a namespace would be something likepull unison.public.distributed.latest lib.distributed,with dots,.,indicating namespace segments.

When we'rewithina project, the existing UCM commands for navigating and viewing namespaces work as before. Let's take a look at thedistributedproject we just pulled in.

helloProjects/myNewBranch> ls lib.distributed

  1.  Binary           (type)
  2.  Binary/          (4 terms)
  3.  Buffer           (type)
  4.  Buffer/          (29 terms)
  5.  Chain            (type)
  6.  Chain/           (38 terms)

Open up a scratch.u file in a text editor window and add the following Unison code to it. Save the file when you're ready to add it to the codebase.

  # Hello Projects

  This is a simple Unison project.

helloWorld : '{IO, Exception} ()
helloWorld = do
  printLine ("Hello" ++ "yourName")

Use theaddcommand in the UCM so thehelloWorldfunction will be present inmyNewBranch.In Unison, we don't have specific named "commits", just additions and updates to the codebase state.

We'll merge this branch back into themainbranch next.

helloProjects/myNewBranch> add

  ⍟ I've added these definitions:

    README     : Doc
    helloWorld : '{IO, Exception} ()

mergetakes two arguments, the source and the destination, respectively. We can indicate that we are merging abranchinto another branch by prefixing the branch name with a slash.

helloProjects/myNewBranch> merge /myNewBranch /main

  Here's what's changed in helloProjects/main after the merge:

  Added definitions:

    1. README     : Doc
    2. helloWorld : '{IO, Exception} ()

  Tip: You can use `todo` to see if this generated any work to
       do in this namespace and `test` to run the tests. Or you
       can use `undo` or `reflog` to undo the results of this
For many of the UCM commands for managing projects, you can drop the project name from the command if you are referencing the same project that your UCM prompt is currently working in. Somerge helloProjects/myNewBranch helloProjects/maincan be represented with just/myNewBranchand/main,respectively.

Switch back to the main branch with theswitchcommand, and optionally delete your old feature branch. Now that we've merged our changes into themainbranch, we can push our project to Unison Share.

helloProjects/myNewBranch> switch main
helloProjects/main> delete.branch myNewBranch

First log into Unison Share with theauth.logincommand. Once logged in, we'll use thepushcommand to do this. Pushing a project to Unison Share will automatically create aremote mappingbetween the local branch and the remote branch.

helloProjects/main> push

Head to the Unison Share url displayed by the UCM to view your project. You'll see that themainbranch is hosted there and the project's welcome page includes your README.

Finally, head back to the root of your codebase withcd .and view a list of your projects with theprojectscommand. You can always get back to your project with theswitchcommand.switch helloProjectswill take you back to the last branch you were working on.

helloProjects/myNewBranch> cd .
.> projects

  1. helloProjects

.> switch helloProjects

Hooray! You have just created what we hope will be the first of many new Unison projects! Happy coding! 😎

More about projects in Unison

🌟Full list of common workflows for projects

🌟Migrating a library from namespaces to projects

📚Projects FAQ's

📚Codebase organization