hav
Getting started

hav in 5 minutes

A hands-on first run on a toy project. No git knowledge is assumed, but if you have it: there is no staging area, no checkout, and merges never block. Every command below is copy-pasteable in order.

1. Make a repo

mkdir toy && cd toy
hav init

init created:

  • a buoy named main, a named pointer into history (a branch, minus checkout state);
  • a knot for this workspace, your unit of work-in-progress. The working directory is the knot, so there is no staging and no "uncommitted changes" limbo.

That's all it created. One thing to know before using hav on a real project: every file not ignored gets captured on the next command. hav ships no ignore rules of its own, so run hav preview to see what a capture would ingest, then write a .havignore (gitignore syntax) covering your build output and dependencies (target/, node_modules/, .venv/, .git/, …). If you skip this, the first capture tells you its size and asks before storing anything when the tree looks like an unignored dependency tree.

2. Edit, look around

echo 'fn main() {}' > app.rs
hav st

st shows your knot, the buoy it's based on, and the diff. There was no add and no commit. Every hav command starts by capturing the working tree into your knot, so the snapshot already happened.

Name the work in one line saying what it is:

hav describe -m "seed the app"

3. Land it

hav tie

tie is the one merge verb. Your knot gets its parent written and main moves to it, making the work tied history. The workspace automatically starts a fresh knot on top, so you just keep editing.

hav log

4. A second workspace

Need to work on two things at once? Add a workspace instead of switching:

hav ws new ../toy-fix --on main
cd ../toy-fix
echo 'fn fix() {}' > fix.rs
hav describe -m "the fix"
hav tie

Each workspace sits on its own knot, and any number can track the same buoy. "Already checked out elsewhere" is impossible by construction.

5. Sync is explicit

Back in the first workspace, main has advanced (the fix landed):

cd ../toy
hav st          # "behind main by 1 knots — hav sync"
hav sync        # NOW files move, only because you asked

hav never rebases your working tree automatically, because a build might be running. st tells you and sync acts. If the incoming work collides with yours, the conflict is written into your files with markers and recorded as data. Nothing blocks, and there is no --continue. Edit the file marker-free (or run hav resolve <path> --take ours|theirs) and the next command captures the resolution.

6. Undo anything

hav undo        # undoes the last operation, including the files on disk
hav redo
hav op log      # every mutation is a numbered op; the cursor is movable

The journal keeps your last 50 operations by default (hav op limit <n> changes that; 0 = unlimited). hav sweep reclaims the disk space of anything that has aged out of it. Accidentally captured a node_modules/? Ignore it, capture again, and once the fat version ages out, sweep frees it. If you already tied the knot, hav edit​ it and capture again first — sweep only frees what no surviving knot version still pins.

7. Share it (optional)

A remote is a path to another repo, or a URL served by a harbor:

cd .. && mkdir hub && cd hub && hav init --bare && cd ../toy
hav remote origin ../hub
hav push                     # tied history only; WIP never leaves the machine
hav clone ../hub ../toy2     # a colleague's copy

For remotes over HTTP and sealed private buoys, see The harbor and Sealed crews.

Where next

On this page