Conflicts
Status letters, the automatic merge on pull, resolve, merge --abort, and why one conflict holds back only its own part.
Every file, page and workflow in a project remembers the fingerprint (etag) of the server's copy at your last pull. When you push, the server compares that fingerprint with what it has now. If someone changed it in the meantime (a colleague, the customizer, an AI in the admin), the server refuses to overwrite and the CLI reports a conflict. Nothing is lost.
The letters in webmati status
| Letter | Meaning | Next |
|---|---|---|
M | modified here | push sends it |
A | added here | push creates it |
D | deleted here | push deletes it |
N | new on the server | pull takes it |
S | changed on the server | pull takes it |
X | deleted on the server | pull deletes it here |
C | conflict: both sides changed | see the .remote copy, then resolve |
= | the same change on both sides | nothing to send or take |
webmati status --help prints this table; webmati status --json gives the
letters in status.
pull merges when it can
When an item changed on both sides, pull tries to merge:
- text files (Liquid, CSS, JS…) merge by line, like git. Where both sides
edited the same lines, it marks them with
<<<<<<<,=======,>>>>>>>; - JSON (templates,
settings_data.json, pages…) merges key by key, keeping the order of sections and blocks; - workflows merge node by node and edge by edge; canvas positions sort themselves out;
- project files (an app's source, scripts, docs) merge like text, or key by
key when they are
.json. A binary one (an image, a font) cannot merge: it stays a conflict, the server's copy beside it in.webmati/conflicts/.
When your push was the one refused, the next pull does the same for those
items: it merges the server's change into yours. A clean merge becomes your change (M): just push it. An unclean one stays C:
the file holds the merge with markers, and
.webmati/conflicts/<path>.conflict.json lists the collisions.
webmati merge # run the merger again on open conflicts
webmati merge --abort # undo the automatic merges: your copies back, each an open conflict again
Settling a conflict
The server's side is in .webmati/conflicts/<path>.remote. Compare it with your
file and pick one:
webmati resolve theme/sections/hero.liquid --theirs # take the server's version
webmati resolve theme/sections/hero.liquid --ours # keep yours (the next push overwrites the server's)
webmati resolve theme/sections/hero.liquid --merged # your file now holds the merge
--merged refuses a file that still has <<<<<<< markers. Then:
webmati validate
webmati push
Do not use push --force to make a conflict go away
webmati push --forceoverwrites the server's copy you have not pulled: someone else's work is lost. Use it only when you are sure the server's copy should go.
One conflict holds back only its own part
A push travels in parts, each one transaction on the server: the theme, the
workflows, the pages, the project's own files, and the live changes. Within a part, everything lands or
nothing does. A conflict in one theme file holds back the whole theme part (the
other theme files report SKIPPED not sent: the theme changeset has a conflict to resolve first), while workflows and pages are still sent as usual.

