over sync¶
Reconcile a checkout-materialized overlay with its git source: pull upstream changes into the checkout, and push local commits made directly in the checkout back upstream.
Usage: over sync [OPTIONS] [NAME]
Arguments:
[NAME] Name of the overlay to sync (default_overlay if configured, all overlays otherwise)
Options:
-H, --home <HOME> Configuration and overlays root [env: OVER_HOME]
-r, --root <ROOT> The target root directory (~)
-d, --debug Toggle debug traces
--no-uses Do not process uses
-a, --all Sync every overlay, ignoring any configured default_overlay
-v, --verbose Toggle verbose output
--pull-only Only pull upstream changes into the checkout
--push-only Only push local commits to the overlay source
--continue Re-attempt a sync after resolving conflicts manually
--abort Abort an in-progress merge left by a conflicted sync
-n, --dry-run Report what would happen without syncing
--no-prompt Never prompt to commit a virtual checkout's local changes; report them as blocked instead
-h, --help Print help
When NAME is omitted, a configured default_overlay (see
Default Overlay Selection)
narrows the sync to just that overlay; pass --all to sync every overlay
regardless.
Scope: the overlay's root git entry only¶
An overlay's git map can declare two conceptually different things:
- the overlay's own content, cloned to its target root (the
"."entry, or the shorthand single-URL/single-object form) — this is "the overlay itself materialized as a checkout", and the only thingover syncever touches. - nested repositories declared inside the overlay (any other path key,
e.g. a plugin-manager checkout at
.config/nvim/pack/plugins/foo) — a separate concern.over applyensures these exist and are configured as declared, but their content/history is never synchronized byover sync. Manage them with plain git yourself.
What it does¶
For each overlay's root checkout (and, for a worktree/worktrees
bare-repo config, for every worktree directory that exists on disk —
synced independently):
- Refuses to touch a checkout with uncommitted changes. Commit or stash first.
- Fetches
originand fast-forwards or three-way-merges the current branch with its upstream — real git merge machinery, not a custom algorithm. A conflicting merge leaves real conflict markers in the working tree and stops there (no push): resolve with ordinarygit add/git commit, then re-runover sync, or runover sync --abortto discard the in-progress merge (git merge --abortequivalent — your own commits are never touched, only the failed merge attempt). - Pushes the branch to
originif it ended up ahead.
--pull-only/--push-only restrict this to one direction. --dry-run
never performs any network I/O or mutation; it reports what's already
known locally.
What it never does¶
- Touch a dirty working tree, even partially.
- Auto-resolve conflicts, rebase, or invent its own merge algorithm — git's own merge/rebase/conflict tooling is authoritative.
- Synchronize nested (non-root)
gitentries (see above). - Discard local commits:
--abortonly resets an in-progress, uncommitted merge back to the pre-mergeHEAD.
over sync persists a small, informational-only checkpoint under
$XDG_STATE_HOME/over (overlay/checkout association, last synced commit
and outcome). It is never read back to decide correctness — git's own
repository state remains authoritative — so deleting it is always
harmless.
See ADR-014 and the roadmap for the full design rationale.
Virtual checkouts (materialization = "checkout")¶
A virtual checkout — no
.git at the target, backed by the overlay's own source repository — is
reconciled by the same over sync command, but entirely locally: no
network I/O, since the "source" is already the repository over reads the
overlay from.
- Nothing changed anywhere -> up to date.
- Only the source repository moved (nothing local to lose) -> the target
is refreshed automatically (
--pull-only/--push-onlystill apply: gated on the pull direction). - Only the target has local edits -> asks for confirmation (and a commit
message) before committing them into the source repository — the same
as running
over commityourself. Declining, or passing--no-prompt, leaves both sides untouched and reports the checkout as blocked. - The same file changed on both sides, to different content -> reported as a conflict, never auto-resolved; resolve manually (edit the target and/or the source repository directly), then re-run.
--dry-run never prompts and never mutates anything for a virtual
checkout either, matching its root-Checkout behavior above.