The Unison Codebase Manager has a powerful set of commands for managing the state of your codebase. Other programming languages will make use of version control systems like Git (or spamming Ctrl-Z) to manage history, but in Unison changes to the codebase, such as updating terms or deleting them, are automatically preserved as a log of hashes in the UCM itself. One of the UCM's useful features is the ability to view and rewind the log of your codebase to a previous point in time.
A walk-through
What does it actually look like when we say that the UCM creates a log of changes to the codebase? Let's walk through a simple example.
Viewing changes to a branch
Say we have the Unison term magicNumber = 40
that we add
to a fresh project.
scratch/main> add
⍟ I've added these definitions:
magicNumber : Nat
Realizing that our magic number is actually 42 and that we're missing another term, we can make those changes in our scratch.u file and then update
the codebase.
magicNumber = 42
magicWord = "please"
Let's inspect the reflog
to see what it looks like:
scratch/main> reflog
Below is a record of recent changes, you can use
`reset #abcdef` to reset the current branch to a previous
state.
Tip: Use `diff.namespace 1 7` to compare between points in
history.
Branch When Hash Description
1. scratch/main now #8lffaev34c update
2. scratch/main now #cr3um0rgg1 add
3. scratch/main now #sg60bvjo91 Project Created
The reflog
command displays a log of changes to the current branch along with the UCM command that produced that change.
Resetting the state
If we want to revert the latest update, we have two options, undo
and reset
.
undo
rewinds the most recent change to the current branch:
scratch/main> undo
Here are the changes I undid
Updates:
1. magicNumber : Nat
↓
2. magicNumber : Nat
Added definitions:
3. magicWord : Text
Because changes to a Unison codebase form an immutable log, this command also shows up in the reflog:
scratch/main> reflog
Below is a record of recent changes, you can use
`reset #abcdef` to reset the current branch to a previous
state.
Tip: Use `diff.namespace 1 7` to compare between points in
history.
Branch When Hash Description
1. scratch/main now #cr3um0rgg1 undo
2. scratch/main now #8lffaev34c update
3. scratch/main now #cr3um0rgg1 add
4. scratch/main now #sg60bvjo91 Project Created
If we need to move farther backward in the log, we can use the reset
command with the hash of the state we want to return to:
scratch/main> reset #cr3um0rgg1
Viewing changes across multiple branches in a project
Let's create a feature branch for this example and make some new changes.
scratch/main> branch addFeature
magicNumber = 1
magicWorld = "pretty please"
reflog.project
will show the changes across all branches in the project:
scratch/addFeature> reflog.project
Below is a record of recent changes, you can use
`reset #abcdef` to reset the current branch to a previous
state.
Tip: Use `diff.namespace 1 7` to compare between points in
history.
Branch When Hash Description
1. scratch/addFeature now #4lotqj3cbo update
2. scratch/addFeature now #8lffaev34c Branch created from scratch/main
3. scratch/main now #8lffaev34c update
4. scratch/main now #cr3um0rgg1 add
5. scratch/main now #sg60bvjo91 Project Created
Compare this to the history
command output, which includes the name of the terms that were changed in the project across its branches:
scratch/addFeature> history
Note: The most recent namespace hash is immediately below this
message.
⊙ 1. #4lotqj3cbo
+ Adds / updates:
magicNumber magicWorld
⊙ 2. #8lffaev34c
+ Adds / updates:
magicNumber magicWord
□ 3. #cr3um0rgg1 (start of history)
Global codebase state
This is less common, but if you need to view changes across the entire codebase, you can use the reflog.global
command.
The deprecated reset-root
command had the ability to move backwards across the entire codebase state, but this is not recommended as it can lead to rewinding changes in unintended projects.