Artifact 023394beafc116cdabd46daff234f08b40e4d016ee68c8baeee720c1bd705842:
- File docs/RELEASE-NOTES-0.3.39.md — part of check-in [938da971fb] at 2026-10-06 21:17:25 on branch trunk — Release 0.3.39 (user: dmestas, size: 3359) [annotate] [blame] [check-ins using]
zit 0.3.39
zit 0.3.39 lets a forge show a conflicting merge the way zit sees it and
record the author's resolution of it, both without a checkout. zit
merge-tree gains -F json, which reports every conflicting file and the
regions of its merge, and --commit, which records the merge with
resolutions the caller supplies.
No artifact, tag namespace, wire, or on-disk repository format changed.
The merge as JSON
zit merge-tree BRANCH --into TARGET -F json
prints one JSON document and writes nothing. It gives the verdict (clean,
up-to-date, conflict or unrelated), the base, current (TARGET) and other
(BRANCH) check-ins, and every conflicting file. A file carries its kind
(text, binary, add-add, delete-modify, modify-delete or
unreadable) and each side's blob and mode, with null where the path is
absent. A text file also carries the regions of the merge: same, current,
other, both or conflict, each as half-open line ranges in base, current
and other. The regions cover each file in order, so a page can draw all three
panes and the merged result from them without merging again.
The regions come out of the same loop that produces zit's merged bytes, so
the page cannot show a merge different from the one zit merge makes. The
order of the names picks the sides: to show a branch as "ours", name the
branch as TARGET.
The exit status is the same as without -F json: 0 clean or up to date, 5
for conflicts, 1 for unrelated check-ins. Every verdict prints a document, so
a caller parses one format.
A store that lacks the content of a file both sides changed reports that file
as unreadable instead of failing.
Settling a conflict
zit merge-tree BRANCH --into TARGET --commit --resolved DIR [--delete PATH]...
-m MESSAGE [--user NAME] --expect-current HASH --expect-other HASH
records the merge of BRANCH into TARGET on TARGET's branch. DIR holds the
resolved content of each conflicting path; --delete PATH resolves one by
removing it. Every other path is the merge's own. The check-in is the one
zit merge and zit commit in a checkout would make with the same answers,
and its check-in HASH on BRANCH line goes to stdout as commit prints it.
Nothing is written when:
- the answers are not exactly the conflicting paths (exit 1);
- an answer still holds a conflict marker (exit 1);
- the store lacks the content of a conflicting file (exit 1);
- TARGET or BRANCH has moved since the page was drawn, that is, either is no
longer the check-in
--expect-currentor--expect-othernames (exit 5, so the caller reads again and redraws).
The merge runs in a working area of its own beside the repository, removed afterwards, and the check-in syncs the way any check-in does.
Compatibility
zit merge-treewith--outor--tarbehaves as before, byte for byte.-F jsonand--commitexclude--out,--tarand each other; giving more than one is a usage error.--resolved,--delete,-m,--userand the--expectoptions are usage errors without--commit.
Qualification
zig fmt --check, zig build test, e2e, smoke (19 scenarios),
git-import-e2e, git-export-e2e, dst, and every fuzz target, whose
three-way merge target now also rebuilds each side of a merge from its
regions, plus the three-runner battery.