Skip to content
zit Artifact [614189c9b0]
Login

Artifact [614189c9b0]

Artifact 614189c9b06e57a5b197e80a99813c36a47be01485484c5d92953d709f91982d:


# zit 0.3.28

zit 0.3.28 adds the counterpart to `config import`, so a configuration area
can be backed up before it is replaced, and lets `merge --probe` answer a
whole stack of branches the way a landing will meet them.

No artifact, tag namespace, sync message, or on-disk repository format
changed.

## `zit config export AREA [FILE]`

`config import` replaces a configuration area from a file and `config merge`
folds one in, but nothing wrote the current area out. The round trip is the
point of the pair: back the table up, replace it, restore it if needed.

```
zit config export user backup.txt
zit config import other.txt
zit config import backup.txt      # the table is back as it was
```

The output is fossil's `configuration export` format: a `#` banner, then one
`config /AREA SIZE` card per row, byte-identical to what the sync protocol
carries for that area — the same cards `import` and `merge` read and the
same cards a fossil repository writes. FILE absent or `-` is stdout. The
file carries no timestamp, so two exports of an unchanged table are the same
bytes and a backup can be compared with `cmp`. The user area includes
password hashes; the help says to treat the file as you would the
repository.

`import` and `merge` now also read `/shun` cards; before, they counted them
as an area zit does not model and skipped them. Shun rows are **added in
both modes**. `import` still replaces the user table, but replacing the shun
table would un-shun whatever the file does not name, and a shun is never
undone here — not by `zit shun`, and so not as a side effect of restoring a
backup. `config pull` already held that line. The round trip is therefore
exact for `user` and add-only for `shun`.

The wire and a file now share one `/shun` payload parser, so a file cannot
admit a row the wire would refuse.

## `zit merge --probe` answers a stack

`merge --probe NAME --into TARGET` answers whether one branch merges cleanly
into one target. A stacked landing asks something else: whether rung 3
merges into the target *once rungs 1 and 2 are on it*. Probing each rung
against the one below cannot answer that, because it knows nothing of what
the target changed in the meantime. It can call a rung clean that stops the
landing.

Given several NAMEs, `--probe` now answers the landing's question:

```
$ zit merge --probe --into trunk r1 r2 r3 r4
merges   r1 clean
merges   r2 clean
merges   r3 conflict (1)
conflict f.txt
merges   r4 not-reached
```

Each rung is merged, in memory, onto the target with the rungs before it
already landed. A rung after one that stopped is `not-reached`: a merge that
did not complete leaves nothing to continue from. A rung already inside the
landed tree is `up-to-date` and the chain continues. Still read-only, still
exit 0 in every case. One NAME prints exactly what it always has, and a
real merge still takes one NAME.

Two things make the chain more than a loop over the existing probe:

- **The landed tree is held as content, not names.** The single probe
  compares file hashes and only reads blobs to decide a conflict. A cleanly
  merged file has no name in the store until someone commits it, so the
  next rung's side is a map of stored blobs *or* merged bytes.
- **The merge base moves with the landing.** Once rung 1 has landed, the
  target's tip has it as an ancestor, so rung 2's base is the nearest common
  ancestor with anything landed, not the target's old fork point. Merging
  the landed tree against the old fork point would see rung 1's edit on one
  side and rung 2's rewrite of it on the other, and report a stacked rung
  as conflicting with its own parent. The test for this was checked by
  breaking the base on purpose: it then reports exactly that false conflict.

## Compatibility

- No on-disk repository or wire format changed; Fossil RFC revision 00
  remains the target.
- `zit config import|merge` now apply `/shun` cards (add-only) instead of
  ignoring them. The summary prints one line per area touched.
- `zit merge --probe` with more than one NAME was previously refused as an
  extra argument; it now probes the chain.

## Qualification

`zig fmt --check`, `zig build test`, `e2e`, `smoke`, `git-import-e2e`,
`git-export-e2e`, and `dst`, plus the three-runner CI battery.