@vd7/gitty
v0.6.14
Published
snapshot checkpoint CLI: gitty + gittysnap + gittyunion (content first)
Maintainers
Readme
flowchart LR
T[tree] --> Q{can this path land?}
Q -->|yes| P[commit + push]
Q -->|conflict / too big / submodule| H[hold back]
P --> R[keep going]
H --> R
R --> F{anything still blocked?}
F -->|held some| D[remote has the rest]
F -->|nothing landed| K[park bak/pending-merge]Issue
❌ All-or-nothing stall
one conflicted, oversized, or submodule path parks the whole checkpoint
the rest of the tree sits unbacked on that machine
drip: push the clean subset; hold the rest; never stall the backup
❌ Dual-machine strand
laptop + desktop both edit
N local commits replay against remote -> same conflict N times
other machine's work never left that machine
❌ Checkpoint friction
agents touch many repos per session
add+commit+pushper repo burns timeone blocker used to abort the whole run
❌ Append ledger false conflicts
two hosts append different
.ndjson/.jsonllinesgit sees one slot, two lines -> conflict
nothing was edited; both lines should keep
Options
| | Bin | Job | When |
|---|---|---|---|
| | gitty | drip + holdback -> commit -> push | default backup |
| | gittylfs | same + LFS track | big binaries |
| | gittyembedded | submodules then parent | dirty nested repos |
| | gittyhealth | report only | inspect / mid-op |
| | gittysnap | snap -> merge -> abort clean | solo multi-machine |
| | gittyunion | NDJSON union driver | append ledgers |
Separate bins. Same package. Plain gitty != gittysnap.
Setup
# scoped package; same bin names
npm i -g @vd7/gittyOptional resolvers (missing file -> empty allowlist -> drip/park, no auto-resolve):
per_host:
paths:
- registry/system-resource/manifest.json
globs:
- snapshots/$(hostname)/**
semantic_union:
globs:
- "**/*.ndjson"
- "**/*.jsonl"
key_field: tsUsage
| path | do this | get this |
|---|---|---|
| A | gitty | drip + holdback checkpoint on remote |
| B | gittysnap | snapshot-first solo sync |
| C | gittyunion install | NDJSON union merge driver |
Path A · gitty
# land whatever can land; hold blockers; park only if nothing can
gitty "checkpoint" "$HOME/Documents/a/gitty"GITTY_PARTIAL=1 default. Park-only: GITTY_PARTIAL=0. Bulldoze: GITTY_FORCE=1.
Path B · gittysnap
# both hosts on remote first; rc=2 on conflict; worktree clean
gittysnapPath C · gittyunion
# union + dedupe + stable-sort for .ndjson / .jsonl
gittyunion installOutput
| signal | meaning |
|---|---|
| partial integrate | resolved subset committed; held paths stay local |
| holdback | oversized / submodule / push-reject left unstaged |
| park | nothing could land; bak/pending-merge-* + remote-snapshot-* |
Local branch stays put on park. Nothing lost.
Gotchas
| problem | fix | stability | why |
|---|---|---|---|
| one unresolvable file parks whole merge | drip (GITTY_PARTIAL=1): commit resolved subset | stable | backup as much as possible |
| oversized path blocks push | leave GITTY_PARTIAL=1 | stable | hold back; push the rest |
| N-commit rebase replays same conflict N times | merge --ff-only then --no-ff once | stable | one merge, one conflict set |
| per-host artifact conflicts every sync | .gitty/additive-resolvers.yaml per_host | stable | ours on that host; --no-ff keeps both parents |
| .ndjson append conflict | semantic_union or gittyunion install | stable | union + dedupe + stable-sort |
| fresh clone drops union driver | re-run gittyunion install | stable | attrs alone insufficient |
| nothing can land | park bak/pending-merge-* | stable | first-class ref; nothing lost; non-fatal |
| foreign-owned .git (old sudo git) | sudo chown -R "$(whoami)" .git | stable | fail-fast; GITTY_SKIP_PERM_CHECK=1 opt out |
Docs
| Doc | Topic |
|---|---|
| docs/README | index |
| docs/commands | all bins |
| docs/gittysnap | snapshot-first sync |
| docs/gittyunion | NDJSON union driver |
| docs/partial-commit | holdback + drip |
| docs/environment | env |
| docs/hooks | repo hooks |
npm tarball = bin/ + README only. docs/ is GitHub.
Contact
