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 : NatRealizing 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 CreatedThe 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 : TextBecause 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 CreatedIf 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 #cr3um0rgg1Viewing changes across multiple branches in a project
Let's create a feature branch for this example and make some new changes.
scratch/main> branch addFeaturemagicNumber = 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 CreatedCompare 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.