Merge
Three-way merge for combining divergent branches.
Merging combines the changes from one branch into another. Omnigraph uses a three-way merge algorithm — the same strategy used by git — to detect conflicts and apply non-conflicting changes automatically.
Merge command
omnigraph branch merge --uri ./repo.omni feature-x --into mainThis merges the changes from feature-x into main. After a successful merge, main advances to a new snapshot that includes both its own changes and those from feature-x.
Add --json for structured output:
omnigraph branch merge --uri ./repo.omni feature-x --into main --jsonThree outcomes
Every merge resolves to one of three outcomes:
| Outcome | Meaning |
|---|---|
already_up_to_date | The target branch already contains all changes from the source. Nothing to do. |
fast_forward | The target branch has no new changes since the fork point. The pointer moves forward. |
merged | Both branches have diverged. A three-way merge produces a new snapshot on the target. |
How three-way merge works
When both branches have diverged from their common ancestor, Omnigraph performs a three-way merge:
1. Find the merge base
The merge base is the most recent snapshot shared by both branches — the point where they diverged. Omnigraph walks the snapshot history of both branches to find this common ancestor.
2. Diff each branch against the base
Two diffs are computed:
- Source diff — what changed on
feature-xsince the merge base. - Target diff — what changed on
mainsince the merge base.
Each diff is a set of per-row changes classified as inserts, updates, or deletes.
3. Apply non-conflicting changes
Changes that appear in only one diff are applied directly:
- A row inserted only on the source branch is added to the target.
- A row updated only on the source branch has its updates applied.
- A row deleted only on the source branch is removed.
The same logic applies symmetrically for changes that appear only on the target side — those are already present and are preserved.
4. Detect conflicts
A conflict occurs when both branches modify the same data in incompatible ways. Omnigraph classifies conflicts into the following types:
| Conflict type | Description |
|---|---|
| Divergent update | Both branches updated the same row with different values for the same property. |
| Delete vs. update | One branch deleted a row that the other branch updated. |
| Duplicate insert | Both branches inserted a row with the same @key value but different data. |
| Orphan edge | An edge references a node that was deleted on the other branch. |
| Constraint violation | The merged result would violate a schema constraint (e.g., @unique, @range). |
| Type mismatch | A property was set to incompatible types across the two branches. |
| Cardinality violation | The merged edge set would exceed a declared cardinality limit. |
When conflicts are detected, the merge fails and the conflict details are returned. The target branch is not modified.
Inspecting before merging
Before merging, you can read from both branches to understand what will change:
# Check the current state of main
omnigraph snapshot ./repo.omni --branch main
# Check the state of the source branch
omnigraph snapshot ./repo.omni --branch feature-xRun queries against both branches to compare results:
omnigraph read ./repo.omni \
--query queries.gq \
--name count_tasks \
--branch main
omnigraph read ./repo.omni \
--query queries.gq \
--name count_tasks \
--branch feature-xThis lets you verify the effect of a merge before committing to it.