graflo.architecture.evolution.merge_commit¶
Recording a merge as a commit.
Deliberately not in merge.py. That module is the pure algorithm: two
manifests in, one out, no notion of a store or of history. Stamping and
recording are what a commit point does to the result afterwards -- the same
separation contract/provenance.py draws to keep provenance out of
apply_evolution, and for the same reason. A merge that recorded its own
lineage could not be run twice without inventing two different histories.
A merge commit is materialized exactly as a merge commit is: its ops are the
verified diff from its first parent, so first-parent replay and hash
verification need no special case anywhere downstream. What makes it a merge
rather than a merge is the declaration that rides alongside it -- a
:class:~graflo.architecture.evolution.merge3.MergeRecipe of kind merge,
which is what a re-merge reads.
Attributes¶
__all__ = ['build_merge_commit', 'find_commit_by_tree']
module-attribute
¶
Classes¶
Functions:¶
build_merge_commit(left, merged, *, parents, recipe, right=None, label=None, created_at=None, notes=None)
¶
Record merged as a merge commit over parents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
GraphManifest
|
The first parent's manifest -- the side the ops are diffed from. |
required |
merged
|
GraphManifest
|
The merge result. |
required |
parents
|
list[str]
|
Parent commit ids, first parent first (at least two). |
required |
recipe
|
MergeRecipe
|
The recorded declaration, so a re-merge can replay it. |
required |
right
|
GraphManifest | None
|
The second input. When given, the relabel the merge applied to
left is recorded ahead of the diff (see :func: |
None
|
label
|
str | None
|
Short human-readable name. |
None
|
created_at
|
str | None
|
ISO-8601 timestamp. |
None
|
notes
|
str | None
|
Free-form annotation. |
None
|
Raises:
| Type | Description |
|---|---|
CommitError
|
Fewer than two parents, or the derived diff does not reproduce merged -- which happens when the two sides differ somewhere no op reaches. |
Source code in graflo/architecture/evolution/merge_commit.py
find_commit_by_tree(history, manifest)
¶
The commit whose recorded tree is this manifest's content address.
How a file path becomes a commit id without the caller naming one: a manifest is its content hash, and a commit records the tree it produced, so the two meet without any extra bookkeeping.
More than one commit can legitimately reach one tree -- two routes to the same world model are the case content addressing exists to recognise. When that happens a head wins, because that is the state someone is working from; failing that the lowest id, so the answer never depends on store order.
Source code in graflo/architecture/evolution/merge_commit.py
left_relabel_ops(left, right, recipe)
¶
The relabel a merge applied to its left side, as ops.
merge_manifests resolves its declared clusters and canonical maps into
one composite canonicalize per side and applies it before the union,
preceded by the retype its field_types declare for that side.
The left one is part of how the merged manifest came from the left, so a
merge commit records it first. Resolved from the recorded declaration --
the whole op, canonical maps included -- against both sides, exactly as
the merge resolved it.
Source code in graflo/architecture/evolution/merge_commit.py
lift_recorded_merge_op(payload)
¶
A recorded merge declaration in the current op vocabulary.
Authored op documents are refused when they use a removed key, naming its
replacement; a recorded one is history and cannot be edited, so it is
translated: vertices / relations to the *_equivalences lists,
resource_renames to renames.right.resources, an op-level
acknowledgement onto every vertex equivalence, fuse_right to
union_right, and allow_merges dropped.