hav for git users
hav has a different core model from git, and a few git instincts actively mislead. This page gives you the translation table, then the habits to unlearn.
The rosetta table
| You want to… | git | hav |
|---|---|---|
| Create a repo | git init | hav init |
| See what's changed | git status + git diff | hav st |
| Record work | git add + git commit -m | hav describe -m names it; the snapshot already happened |
| Publish onto a branch | git merge / git rebase + push | hav tie |
| Start the next unit of work | git checkout -b | hav new, or keep editing and let tie start a fresh knot |
| Throw away WIP | git reset --hard / git stash drop | hav discard (undoable) |
| A branch | branch | buoy, a named pointer that never holds checkout state |
| Work on two things at once | git worktree add (one checkout per branch) | hav ws new (any number per buoy) |
| Bring in upstream changes | git pull / git rebase | hav sync, explicit, into your workspace |
| Look at history | git log | hav log |
| Inspect one commit | git show | hav show |
| Amend / rewrite | git commit --amend, git rebase -i | hav edit, hav squash, hav split, hav absorb; descendants auto-rebase |
| Fix up earlier commits | git absorb / manual fixup dance | hav absorb |
| Undo a mistake | reflog spelunking | hav undo (files included) |
| Share | git push / git pull | hav push / hav pull (fast-forward-only; reconcile with tie) |
| A bare repo to push to | git init --bare | hav init --bare |
| Serve repos over HTTP | git daemon / a forge | hav harbor serve |
| Ignore files | .gitignore | .havignore (same syntax) |
Habits to unlearn
Stop staging
There is no index. Every hav command begins by capturing the working tree into
your current knot, so by the time you type hav st, the snapshot exists.
describe names it and tie lands it. The one thing the staging area gave
you, committing part of your tree, is hav split (by file or by hunk), a
curation step you run after the work.
Stop thinking of branches as places
A buoy is a pointer to a knot, and that is all it is. You are never "on" a
buoy; your workspace tracks one. Checking out doesn't exist, and switching
doesn't exist. If you need to work on something else, make another workspace
(hav ws new). Workspaces are cheap database rows, and any number can track
the same buoy.
Stop fearing history rewrites
In git, editing an old commit orphans every descendant and hands you the
pieces. In hav, edit an old knot and every tied descendant re-merges
automatically. Conflicts, if any, are stored as data in the descendants, and
buoy heads keep their ids. Squash, split, and absorb are everyday moves.
Stop expecting merges to stop you
tie and sync always complete. If content collides, the conflict is
recorded inside the resulting snapshot and materialized as markers in the
tree of whoever needs to resolve it. Nothing is "in progress", and there is no
--continue or --abort. Fix the file (or run
hav resolve --take ours|theirs) whenever you like, and the next command's
capture notices.
Stop expecting pull to touch your files
hav pull moves history between repos and fast-forwards the local buoy. It
never merges and never touches a working tree. Your workspace then says
behind main — hav sync, and files move only when you run it. Nothing ever
rewrites a tree that an agent or a build might be using.
Push is fast-forward-only
Divergence is reconciled locally. There is no force-push and no
merge-on-push. If the remote moved, pull fetches it, tells you the histories
diverged, and prints the recipe: tie the remote head into your buoy (an
ordinary merge, conflicts as data), then push.
Things git doesn't have
- Untied knots. Work that hasn't landed has no parents yet, only a base.
History is written at land time (
tie), so the everyday flow yields linear history without rebase ceremony. See The model. - The op journal. Every mutation records a full before/after view, and
hav undorestores state and disk. It is the reflog, if the reflog covered everything and included your files. See Undo. - Sealed crews. Encrypted lines of work inside a shared repo, revealed by
an ordinary
tie --revealwith ids unchanged. See Sealed crews.
Things hav deliberately lacks
- No git bridge. No import, no export. The way in is files; the way out is files.
- No hooks. Nothing runs code on your behalf during a command.
- No force-push, no
--hard, no destructive flags. Destruction is scoped to two explicit verbs (op limit,sweep) with consent gates. - No hosted service. Remotes are paths, or harbors you run yourself.