Skip to content

Project Branching

Project branches let you create isolated snapshots of a project's artifact pins and configuration, experiment freely, and merge changes back into the main line when you are ready. This is separate from artifact-level DAG branching, which tracks individual artifact version history.

Feature flag required. Project branching is gated behind the dvcs_branching_enabled feature flag. See Enabling the feature flag below.


Overview: Project branches vs. artifact branches

Concept Scope What it tracks
Project branch Whole project Which artifact versions are pinned per project; project-level config
Artifact branch (DAG) Single artifact Individual artifact content versions and merge history

Project branches are coarse-grained: switching a project branch swaps the entire set of artifact pins in one operation. Artifact branches are fine-grained: they track content changes inside a single artifact. The two systems compose — artifact-level version resolution happens inside the ProjectGraphService during a project merge.


Enabling the feature flag

Project branching is disabled by default. Enable it in your deployment:

SKILLMEAT_DVCS_BRANCHING_ENABLED=true skillmeat web dev
SKILLMEAT_DVCS_BRANCHING_ENABLED=true

Set dvcs_branching_enabled = true in your enterprise settings panel or via the admin API.

When the flag is off, all branch API endpoints return 404 and the CLI prints:

Branching is disabled (dvcs_branching_enabled=false). Enable the feature flag to use project branches.

The implicit main branch

Every project automatically has a main branch. It is created lazily on the first project mutation after the flag is enabled; existing projects are backfilled with a main branch row during the feature migration. The main branch:

  • Is marked is_default: true.
  • Cannot be deleted.
  • Is the target for most merge operations.

Managing branches via the web UI

Viewing branches

Open a project's detail page. When dvcs_branching_enabled is on, a branch picker appears in the project header showing the current branch (default: main).

Creating a branch

  1. Open the branch picker dropdown.
  2. Select New branch at the bottom of the list.
  3. Enter a branch name and optionally choose a parent branch.
  4. Click Create.

Switching branches

Select a branch from the branch picker. The page re-fetches project artifacts filtered to that branch's head state. The ?branch=<name> query parameter is reflected in the URL.

Merging branches

  1. Click the Merge button (visible on non-default branches).
  2. In the Merge dialog, confirm the source and target branches.
  3. Click Merge. The merge saga runs server-side.

If the merge is partial (some artifacts could not be resolved automatically), the dialog shows:

Merge partially complete — some artifacts could not be resolved automatically.

Retry the merge with the same token to resume. See Known limitation: partial merge recovery.

Deleting a branch

Use the branch picker overflow menu to delete a branch. You will be asked to confirm. The main branch cannot be deleted.


Managing branches via the CLI

All branch subcommands require dvcs_branching_enabled=true. They work in both local and enterprise editions; enterprise calls authenticate via the configured PAT.

List branches

skillmeat project branch list <project_id>

Output is a table with columns: Branch Name, Default, Visibility, Created At.

Create a branch

# Fork from the project default branch
skillmeat project branch create <project_id> experimental

# Fork from a specific parent
skillmeat project branch create <project_id> hotfix --parent main

# Create a private (user-only) branch
skillmeat project branch create <project_id> draft --private

Switch branches (local CLI context)

skillmeat project branch switch <project_id> experimental

This writes projects.<project_id>.current_branch = experimental to ~/.skillmeat/config.toml so subsequent CLI commands that accept a --branch option default to that branch.

Merge branches

# Merge experimental into main
skillmeat project branch merge <project_id> --source experimental --target main

# Idempotent retry with a fixed token
skillmeat project branch merge <project_id> --source experimental --target main \
  --token 550e8400-e29b-41d4-a716-446655440000

If the merge is partial, the CLI outputs a warning and exits 0. Rerun with the same --token to resume.

Delete a branch

# With confirmation prompt
skillmeat project branch delete <project_id> old-feature

# Skip prompt
skillmeat project branch delete <project_id> old-feature --yes

Branch visibility

Branches have a visibility field:

Value Meaning
team_shared Visible to all project members (default)
user_private Visible only to the branch creator

User-private branch management UI is minimal in the current release. Full private-branch UX is planned as a follow-on. See Known limitation: user-private branch UX.


Known limitations

Partial merge recovery

When a project merge saga fails partway through (for example, one artifact's merge produces a conflict), the project is left in a partial state. The idempotency token allows safe retry:

skillmeat project branch merge <project_id> \
  --source experimental --target main \
  --token <uuid-from-first-attempt>

A formal recovery workflow (resume endpoint) is being designed and will be available in a future release.

User-private branch UX

The schema supports user_private branches, but the filter logic and management surface are minimal in this release. Private branches can be created via --private flag but do not yet have a dedicated management page.