zit 0.7.3 makes import-git take the history Git itself stores, where
0.7.2 stopped on the Linux kernel's with a bare Malformed. Git tags
import under their own names, and a store imported by an earlier
release is renamed on its next --into. A shunned tag can no longer
push a seed's date backwards and hold horizon clones at the content
horizon. A push no longer asks the origin for content, as Fossil's
never does, and the deterministic simulation passes its whole sweep
again.
This release is from trunk. Stores are unchanged from 0.7.2.
import-git takes what Git stores
Old histories hold commits that today's Git would not write, but Git
stores, fetches and exports every one of them. 0.7.2 refused the first
one it met, after doing all the work before it, and said only
Malformed. The Linux kernel's history stopped it twice: 261 identities
with an empty name, and 212 commits that declare a Latin-1 encoding.
The parser's rule is now Git's. An identity in the form
NAME <EMAIL> SECONDS ZONE reads exactly as before, so every check-in
an earlier import wrote keeps its hash. One that is not reads the way
Git reads it:
- An empty name is valid. The check-in's user is the email's local
part (
samfor<[email protected]>). - A missing email, no space before
<, a zone past+2359or a date Git cannot read is taken as Git takes it. A commit with no readable date on one line takes the other line's date. - A date past the year 9999 is clamped to the last date a check-in can carry.
- An annotated tag with no tagger line, as early tags were written, is imported.
Git converts a commit that declares another encoding to UTF-8 as it exports it. Names and messages that are not UTF-8 and declare nothing are kept as their bytes, and the provenance map records them as hex. 0.7.2 refused them as it wrote the map.
A file whose path no checkout can hold is left out of the imported tree.
That covers .. or ., an empty part, a backslash, or a name zit keeps
at the root, such as .zit. 0.7.2 refused the whole history for one.
The import report counts the identities read as Git reads them, and the file entries left out, and names the first of each, so it can be found in Git. An empty name is not counted: it is valid.
A refusal names its record
When the export stream is refused, the report now names the record and
the rule, for example commit febf7ea4bedc: its from is not a mark or a
hex object name. When git fast-export itself fails, the report
points to Git's own message, printed above it, instead of naming a
parse error in the stream Git cut short.
Git tags keep their names
0.7.2 imported a Git tag v1.0 as tags/v1.0 and repeated every branch
as a heads/NAME tag, so zit update v1.0 and a forge's ?t=v1.0
found nothing. Remote-tracking refs became tags that never moved.
Now a Git tag X is the tag X, as fossil import --git names it. A
branch is named by its branch alone, with the name added directly on
its head only when the head sits on another branch's check-in. Refs
outside refs/heads/ and refs/tags/ become no tag. A tag that shares
a branch's name keeps tags/X, so it never stops that branch's name
from propagating.
A store imported by an earlier release is renamed by its next --into,
even when nothing changed upstream. The old names are cancelled where
they stand and the plain ones published, once. The import map records
that, so later runs write nothing.
A shun no longer moves a seed's date back
A seed is dated at the latest tag event in the repository. Shunning a tag removes its events, so a seed minted after a shun could be dated earlier than the one a clone held. The clone refused it as a replay and fell back to the content horizon. A tag pushed with a far-future date and then shunned did this to every horizon clone.
An origin now dates a seed no earlier than the latest date it has
minted. It records that date in .zit-cache/seed-floor. Losing the
record dates the next seed from tag state alone, as 0.7.2 did. The
horizon draft states the rule in Section 5.2.2, and Appendix C records
the change.
A push asks for nothing
Since 0.7.0 an origin has answered a gimme only in a request that
carries a pull card, as Fossil's does. A zit client still sent its
phantoms as gimme cards in a push: names an earlier pull had left
unfilled. Nothing answered them. The client now requests content only
in a pull, a sync or a clone, as Fossil's requests it only when pulling.
The deterministic simulation passes again
The daily soak of the deterministic simulation had failed since 0.7.0, at its 21st seed, on the push above. It stopped there, so the seeds after it went unrun. They now pass in both build modes. The next failure they found was in the horizon sweep's own setup. It chose the file a crashed clone commits by listing the whole tree, so only its fault-free twin fetched the tree nodes the origin withholds. Every seed the soak runs now passes.
Known limits
import-git holds state for every commit it imports, so its memory
grows with the length of the history. The Linux kernel imports past
its first 340,000 commits, the stretch that stopped 0.7.2, with
nothing refused. Its whole history of 1.5 million commits needs more
than 10 GB. Import a history that long on a machine that has the
memory, and leave sub-manifests on: with flat manifests every check-in
writes its whole file list.
Under a structural horizon with the leaves rule, zit leaves can
list a check-in held below the horizon as a leaf. Only the listing is
affected; nothing held is lost or wrong. The simulation reaches this
case past the seeds the soak runs.
Compatibility
Stores are unchanged from 0.7.2. A store imported by 0.7.2 or earlier
keeps every check-in hash. Its tag names change on the next --into.
That writes the renaming controls and an import map at a new version.
An earlier release refuses that map, so a destination renamed by 0.7.3
is added to only by 0.7.3 or later.
On the wire nothing changes.
Qualification
The release manifest records native qualification against the exact tagged source archive on macOS ARM64, Linux x86-64 and Linux ARM64, using the pinned Zig 0.17.0 toolchain. Publication is gated on unit and end-to-end tests, Git differentials, deterministic simulation, seeded fuzzing, and Fossil interoperability checks on every distributed target.
For the basis of the conformance claim, see the 0.1.0 release notes.