Skip to content

DAG Branching & Merge-Back

SkillMeat's DAG (Directed Acyclic Graph) branching system lets you create isolated versions of artifacts, experiment freely, and merge changes back cleanly. This guide walks you through the entire workflow — from creating a branch to resolving merge conflicts.

Enterprise Edition. DAG branching is available in SkillMeat Enterprise with the dvcs_branching_enabled feature flag. Local edition uses linear version history. See Edition Feature Matrix for more.


Overview: Why Branches?

Before DAG branching, artifact versions were linear: v1 → v2 → v3. If you wanted to test a change without affecting the main line, you had to work in a separate collection or project.

With DAG branching, you can:

  • Create parallel timelines — Branch from any version and edit independently
  • Test safely — Experiment without affecting the default main branch
  • Merge cleanly — Bring changes back to main with 3-way merge conflict resolution
  • Cherry-pick — Apply specific commits from one branch to another
  • Track divergence — See which branches differ from main and by how much

Real-world scenario: Your team uses a skill in production (main branch). A developer branches to add a new feature, while another fixes a bug on a separate branch. Both merge back without overwriting each other's changes.


Key Concepts

Branches

A branch is an independent timeline of versions for an artifact. Each branch has a name (e.g., main, feature/auth-v2, hotfix/validator-bug) and tracks its own history.

Default Main Branch

Every artifact starts with a main branch. This is the production baseline — the version most users interact with. You can't delete main, but you can branch from any point in its history.

Parent Branch & Divergence Point

When you create a branch, you choose a parent branch and a point in history (commit). The new branch inherits all versions up to that point, then diverges with its own edits.

Example:

main:     v1 — v2 — v3 — v4 — v5
             \
feature:      — v2' — v3' — v4' (feature/auth)

The divergence point is v2 (the parent commit). feature/auth includes all history up to v2, then adds its own changes.

3-Way Merge

When you merge a branch back to main, SkillMeat performs a 3-way merge using:

  1. Common ancestor — the divergence point
  2. Left side — main branch edits since divergence
  3. Right side — feature branch edits since divergence

If both sides edited different fields, the merge auto-resolves. If both edited the same field, you get a conflict to resolve manually.

Cherry-Pick

Cherry-pick lets you copy a single commit (change) from one branch to another without merging the entire branch. Useful for applying a critical bug fix to multiple branches.


Creating a Branch

Via Web UI

  1. Open an artifact in the Time Machine DAG view (clock icon → DAG tab)
  2. Right-click any version node and select Branch from this commit
  3. Enter a branch name (e.g., feature/v2-rewrite) and confirm
  4. The new branch opens in the editor; all edits go to the new branch

Screenshot: The DAG view shows lanes for each branch; click a node to branch from that point.

Via API

Endpoint: POST /api/v1/artifacts/{artifact_id}/branches

{
  "branch_name": "feature/auth-v2",
  "parent_branch": "main",
  "parent_commit": "abc123def456..."
}

Response (201 Created):

{
  "branch_name": "feature/auth-v2",
  "parent_branch": "main",
  "created_at": "2026-04-11T14:22:00Z",
  "divergence_point": "abc123def456...",
  "ahead_by": 0,
  "behind_by": 0
}


Viewing the DAG

The Time Machine DAG view in the web UI shows your artifact's branching history as a graph:

  • Vertical lanes — one lane per branch
  • Nodes — individual commits (versions)
  • Edges — the flow of history within and between branches
  • Branch badges — color-coded labels showing branch name and status

Interpreting the DAG

  • Nodes on the same lane — history within a single branch
  • Branching point — where one lane splits from another
  • Merge node — where two branches come back together (if merged)
  • Ahead/Behind counts — labels showing divergence from main

Deploy-by-Branch Selector

When viewing deployments or artifact details, use the branch dropdown to:

  • View a different branch — Switch which branch's content is displayed
  • Deploy a branch — Activate a non-main branch for testing or staged rollout
  • Filter history — Show version timeline for the selected branch only

Branch badges on artifact cards indicate: - Active branch (highlight color) - Divergence status (icon: ↔ if diverged from main) - Merge status (icon: ↓ if this branch contains unmerged commits)


Merging Branches

Open the Merge Dialog

  1. Open the artifact in Time Machine
  2. Select the branch you want to merge (from the dropdown)
  3. Click Merge into Main or Merge into [target]
  4. The BranchMergeDialog opens, showing the 3-way diff

Merge Dialog Walkthrough

The dialog displays:

Section Content
Source The branch being merged (e.g., feature/auth-v2)
Target Destination branch (default: main)
Common ancestor Divergence commit hash
Diff summary Fields changed in source and target since divergence
Merge result preview What the merged content will look like
Conflict markers (if any) Fields that need manual resolution

Content-Type-Aware Merge

SkillMeat's merge engine uses different strategies based on artifact type:

Format Strategy Example
YAML Recursive merge on key-value pairs Merges metadata.tags without losing either side's additions
TOML Section-aware merge Combines [dependencies] from both branches
Text (plain skill code) TextMergeDriver — line-based conflict markers Conflicts marked with <<<, ===, >>>
JSON Object-aware merge Merges top-level keys preserving both sides

Clean Merge (No Conflicts)

If no conflicts exist:

  1. Review the merge preview
  2. Click Confirm Merge
  3. A new merge commit is created on main
  4. The branch remains open (not deleted)

Response:

{
  "merge_commit": "def789ghi012...",
  "merged_at": "2026-04-11T14:25:00Z",
  "conflicts_resolved": 0,
  "result_version_hash": "def789ghi012..."
}


Resolving Conflicts

If the same field was edited in both branches, you see a BranchConflictResolutionCard for each conflict.

Conflict Markers

Text-based artifacts show inline markers:

<<<<<<< feature/auth-v2
def validate_token(token: str) -> bool:
    """New token format."""
    return len(token) == 64
=======
def validate_token(token: str) -> bool:
    """Legacy token format."""
    return len(token) == 32
>>>>>>> main

The section between <<<<<<< and ======= is from the branch being merged (source). The section between ======= and >>>>>>> is from the target branch.

Manual Resolution

For each conflict:

  1. Edit the code to keep both changes, one side, or a combination
  2. Delete the <<<<<<<, =======, and >>>>>>> markers
  3. Click Mark as Resolved
  4. Repeat for other conflicts

Example resolved:

def validate_token(token: str) -> bool:
    """New token format; supports legacy fallback."""
    return len(token) in (32, 64)

What Falls into Conflict vs. Auto-Resolve

Scenario Outcome
Source adds field; target unchanged Auto-resolve — field added from source
Both add the same field with different values Conflict — manual resolution required
Source modifies field; target deletes it Conflict — keep or remove?
Both independently add the same lines Auto-resolve (usually) — depends on merge driver
Source edits lines; target edits different lines Auto-resolve — no overlap

Cherry-Picking

Cherry-pick lets you apply a single commit from one branch to another without merging the entire branch history.

When to Cherry-Pick

  • Critical bug fix — Apply a hotfix from main to the feature/v2 branch
  • Selective rollout — Apply just one feature commit to a staging branch
  • Avoid full merge — Extract one change from a messy branch

Via Web UI

  1. Open Time Machine DAG view
  2. Right-click a commit node and select Cherry-pick
  3. Choose the target branch
  4. If conflicts occur, resolve them (same as merge conflicts)
  5. Confirm to create a new commit on the target branch

Via API

Endpoint: POST /api/v1/artifacts/{artifact_id}/branches/{branch_name}/cherry-pick

{
  "source_commit": "abc123def456...",
  "target_branch": "feature/v2"
}

Response (201 Created):

{
  "new_commit": "xyz789uvw012...",
  "cherry_picked_from": "abc123def456...",
  "target_branch": "feature/v2",
  "conflicts_resolved": 0
}


Branch-Scoped Version History

When viewing an artifact's version timeline, you can filter by branch:

  1. Open Version History (clock icon → History tab)
  2. Use the branch dropdown to show only commits from a specific branch
  3. The timeline shows only that branch's commits in order

API: GET /api/v1/artifacts/{artifact_id}/history?branch=feature/auth-v2

This is useful for reviewing what changed on a feature branch before merging.


Enterprise Considerations

Protected Branches

Enterprise admins can mark branches as protected, requiring approval before merge:

  • Prevent accidental overwrites of production (main)
  • Require code review before merge (via RBAC)
  • Enforce required status checks (e.g., tests must pass)

RBAC & Branch Permissions

If your enterprise has role-based access control (RBAC) enabled:

Permission Effect
artifact:branch:create Can create new branches
artifact:branch:delete Can delete branches
artifact:branch:merge Can merge any branch
require_branch_permission Can only merge if you have artifact:branch:merge AND the role-specific branch permission

If you lack artifact:branch:merge, you'll see a 403 Forbidden error when attempting to merge.

Divergence at Scale

Enterprise admins can query divergence across all artifacts and branches:

  • Which branches diverged from main? — Use the admin dashboard
  • How far behind is feature/v2? — Version history shows commit count (ahead_by, behind_by)
  • Force-sync a branch — Admins can reset a branch to match main (destructive; use carefully)

Feature Flag

DAG branching is controlled by the dvcs_branching_enabled feature flag in your server configuration.

To enable (for Enterprise):

  1. Set environment variable: SKILLMEAT_DVCS_BRANCHING_ENABLED=true
  2. Or update config file: skillmeat/api/config.pyAPISettings.dvcs_branching_enabled
  3. Restart the server
  4. The Time Machine DAG view, branch selector, and merge UI become available

If disabled: Artifacts use linear version history only (default behavior).


Troubleshooting

"Branch not found" Error

Cause: Branch was deleted or doesn't exist. Solution: Refresh the DAG view; create the branch again.

"Permission denied on protected branch"

Cause: You lack artifact:branch:merge role or branch is protected and requires approval. Solution: Contact your enterprise admin to grant the role or approve the merge request.

"Unsupported content type for merge"

Cause: Artifact type (e.g., binary image, custom schema) doesn't support 3-way merge. Solution: The system falls back to TextMergeDriver (line-based conflict markers). Resolve conflicts manually or re-export and re-import the artifact.

"Merge created too many conflicts"

Cause: Branches diverged too far (many overlapping edits). Solution: 1. Start a fresh branch from a more recent common commit 2. Discuss changes with your team before merging 3. Use cherry-pick to apply specific, non-conflicting commits first

Conflict Loop (Conflicts Keep Reappearing)

Cause: Two branches keep editing the same line. Each merge leaves markers; re-editing causes new conflicts. Solution: 1. Fully resolve all conflict markers (ensure no <<<<<<<, =======, >>>>>>> remain) 2. Test the merged artifact before considering it done 3. If conflicts persist after resolution, reset and rebase the branch