Skip to content

Branches & Review ​

Every content mutation in Contentrain Studio follows a Git-native workflow. Changes never go directly to your main branch — they are committed to short-lived feature branches and merged through a controlled pipeline. On a project with the review workflow turned on, changes can wait on their branch until a reviewer approves them.

Branch Architecture ​

Studio uses a three-tier branch model:

Studio branch tiers and branch names cr/* feature branches, one per operation, merge into contentrain, the single source of truth. Studio then advances main, your production branch, to contentrain. A feature branch is named cr, then the scope, the target, an optional locale, and a unix timestamp with a random hex suffix, for example cr/content/blog-post/en/1774800862-27c1. cr/* one branch per operation contentrain single source of truth main your production branch merge advance Branch name crprefix/ contentscope/ blog-posttarget/ enlocale (opt.)/ 1774800862-27c1timestamp-suffix

The contentrain Branch ​

The contentrain branch is the single source of truth (SSOT) for all Contentrain-managed content. It sits between feature branches and your main branch.

  • All cr/* branches merge into contentrain first
  • Studio then advances your main branch to match contentrain. This happens in the same operation as the merge, as a fast-forward, so a merge normally lands on both branches at once
  • If your main branch is protected, or has commits that contentrain does not have, Studio first tries to reconcile the two automatically. When that is not possible it opens a pull request titled "contentrain: advance content to main" and tells you "Approved, but not on your site yet: a pull request into your site's branch has to be merged first." The content is already on contentrain; merge the pull request to bring it to your site

The sidebar shows a Branch sync line whenever contentrain and your main branch are not level, for example when content is ahead, when main has changes contentrain does not, or when the two have diverged and a pull request is open.

Feature Branches (cr/*) ​

Every content operation — whether triggered by the AI chat, the content panel, or the API — creates a short-lived cr/* feature branch. Branch names follow the pattern cr/{scope}/{target}[/{locale}]/{timestamp}-{suffix}:

cr/content/{modelId}/{locale}/{timestamp}-{suffix}
cr/model/{modelId}/{timestamp}-{suffix}
cr/new/init/{timestamp}-{suffix}

The scope names the kind of operation: content, model, new (project setup), config (project settings such as locales and glossary terms), media, and a few others. These branches contain exactly one logical change:

  • A content entry was created or updated
  • A model definition was modified
  • Content was copied between locales
  • The project was initialized

The Review Workflow ​

The workflow is a project setting (Project Settings > Workflow):

WorkflowWhat happens to a change
Auto-merge (default)The change is merged into contentrain as soon as it is saved, and your main branch is advanced. The branch is deleted.
Review requiredThe change stays on its cr/* branch until the project's approval policy is met and someone with review rights approves and merges it.

Review required needs a plan that includes the review workflow. On a plan without it, the project merges automatically regardless of the setting.

Branches waiting for review appear under Pending Changes in the project sidebar:

The Pending Changes section in the sidebar, listing a cr/* review branch

A pending change is listed by what it changed (the model name and locale, or a label such as "Project settings") rather than by its Git branch name. A branch a reviewer has sent back shows a changes requested badge.

What Gets Held ​

On a review project, a write is held when the approval policy asks for review for that kind of change. The decision depends on what is being changed, not who is changing it: an owner's edit is held by the same policy as an editor's. The same applies whether the write comes from the content editor, the status picker, the dictionary editor, the vocabulary editor, or the AI agent. When an editor or the agent saves a held change, Studio says it was saved to a branch and needs review before it goes live.

Chat tools follow the project workflow like this:

ToolMerge Behavior
init_projectAlways auto-merges
save_content, replace_in_field, delete_content, copy_locale, update_status, vocabulary, approve_submissionFollows project workflow setting
save_model, delete_model, add_localeFollows project workflow setting
merge_branchManual (user-initiated). On a review project it is refused until the approval policy is met
reject_branchManual (user-initiated)
request_changesDoes not merge; sends the branch back with a comment

Reviewing Changes ​

To review pending changes:

  1. Look at the Pending Changes section in the sidebar
  2. Click on any branch to open the review panel
  3. Read what changed, then approve, request changes, or reject

The Review Panel ​

The review panel describes a change in the project's own terms: entries and fields, not Git files.

The review panel: a field-level diff (old values struck through in red, new values in green) with the approve and reject actions

What the Panel Shows ​

  • Header — the model (or kind of change), locale, who made it and when, with counts of added (+), updated (~) and removed (-) entries
  • Approval card — on a review project: the risk class of the change (for example Content edit, Bulk content or Schema change), a short plan hash, who has approved, and what the policy is still waiting for
  • Changes requested — the reviewer's comment, if the branch was sent back
  • Structure — model changes: fields added, removed, or whose type changed, and a change of title field. A change that can take existing content with it is highlighted with "Existing content may not survive this change."
  • Project settings — languages added or removed, a changed default language, a changed workflow, and glossary (vocabulary) terms added, updated or removed, with the text per locale
  • Entries — grouped by model and locale. Each entry is marked added, updated or removed, and each changed field shows its before and after values. A cleared field is labeled "cleared". In a dictionary, a removed key that reappears under a new name is labeled "possibly renamed from"
  • Other files — files in the change that Studio does not manage as content

Open Technical view at the bottom to see the Git view: every changed file with its status (added, modified or removed) and its content after the change.

Approvals ​

Approval is available on projects with the review workflow. An approval is a decision about one specific version of the change: it records who approved, their role and the exact branch tip they reviewed.

The review panel for a pending change: the approval card with its plan and how many approvals are still needed, the added entry, and the merge button reading "Waiting for approval"

  • Approve — click Approve on the approval card to record your decision
  • Withdraw my approval — the same button becomes this once you have approved. You can withdraw only your own approval
  • Approved — ready to merge — shown when the policy is satisfied. Until then the merge button reads Waiting for approval and is disabled
  • Approved by — lists who has approved so far
  • An approval stops counting when the branch changes after it was given, because a new commit is a different change. The card lists approvals that no longer count and why (for example, "plan hash mismatch" or "commit mismatch"), so you can tell why a change you approved is still blocked
  • Self-approval — with no policy file, the person who made a change may approve it. A policy can forbid this (see below). The AI agent can never approve

Approving needs the same rights as merging: Reviewer, Admin or Owner. A policy can narrow it further to specific roles.

Approving does not merge by itself. Click the primary button, labeled Approve 1 change or Approve N changes, to merge. The merge is pinned to the tip you reviewed: if someone adds a commit after you approved, the merge is refused ("This branch changed after it was approved") and the panel reloads the new version for review.

Requesting Changes ​

Instead of approving or rejecting, a reviewer can send a branch back:

  1. Click Request changes at the bottom of the panel
  2. Write what should change before the branch can be approved
  3. Click Send back

The branch stays open and the comment is shown on the branch, in the review panel and in the sidebar badge. Anyone who can see the branch, usually the author, can click Mark addressed once they have dealt with it. The note is kept as history until the branch is merged or rejected. Merging or rejecting the branch clears the request. A request fires the branch.changes_requested webhook event, and the AI agent can also request changes with the request_changes tool.

Approval Policy ​

The approval policy is optional. It lives in your repository as .contentrain/approval-policies.json and is read from the contentrain branch. Keeping it in Git means a policy cannot be changed in a database between a change being made and being approved. The policy applies only to projects with the review workflow; an auto-merge project never consults it.

Default Behavior ​

With no policy file, every write above read-only needs one approval on the change before it merges, and the person who made the change may give it. This keeps a one-person project usable while still recording who approved what.

Writing a Policy ​

A policy sets how many approvals each kind of change needs. Changes are classified by risk, from lowest to highest: read_only, low_risk_content, bulk_content, destructive_schema, external_effect, financially_material, deployment. Studio classifies writes like this:

  • Content edits are low_risk_content
  • A write that touches more than one entry, any delete, copying a locale or adding a locale is bulk_content
  • A single-entry edit is also treated as bulk_content when it moves the entry to published or archived, empties a field, removes list items, or writes 4,000 characters of text or more
  • Model changes (saving or deleting a model) are destructive_schema
json
{
  "version": 1,
  "allow_self_approval": false,
  "rules": [
    { "risk": "low_risk_content", "gate": "change", "mode": "single" }
  ]
}
FieldMeaning
versionPolicy file version. Use 1
rules[].riskThe risk class the rule applies to. A rule also covers every class above it, except auto rules, which cover only their own class
rules[].gatechange (the diff on a branch), plan (before the work starts), or release (before a publish or deploy)
rules[].modeauto (no approval needed), single (one approval), or quorum (several)
rules[].min_approvalsFor quorum: how many different approvers are needed (default 2)
rules[].rolesOnly these roles can satisfy the rule. Leave out to allow any reviewer
rules[].models, rules[].localesLimit the rule to specific models or locales
default_modeApplied at the change gate when no rule matches. Without it, a change that matches no rule needs nothing
allow_self_approvalSet to false to require someone other than the author. The default when no policy file exists is to allow it

To let small content edits merge on their own while still holding schema changes, trust only that class and set a default for everything else:

json
{
  "version": 1,
  "default_mode": "single",
  "rules": [
    { "risk": "low_risk_content", "gate": "change", "mode": "auto" }
  ]
}

WARNING

Without default_mode, an auto rule means a class it does not cover matches no rule at all and merges without approval. Set default_mode unless that is what you want.

If the file is not valid JSON or has an unknown value, Studio does not ignore it: the default policy applies and project health reports that the approval policy is not usable, with what is wrong.

Releases ​

Approving content and approving a release are separate. A manual Deploy now on a review project is refused ("This release still needs approval before it can be deployed") until the release itself has been approved under the policy. Content approvals never satisfy a release, and release approvals never satisfy a change. Release approvals are recorded by owners and admins through the API: POST /api/workspaces/{workspaceId}/projects/{projectId}/deploy/approve with an optional note, and DELETE on the same path withdraws your approval.

Approvals & Releases ​

On a review project, the project overview has an Approvals & releases entry. Every merge or release that went through an approval is recorded there, with who approved it, who ran it and what it covered. A project that merges without approvals records nothing here.

Merging Changes ​

To merge a branch:

From the UI ​

  1. Open the review panel by clicking the branch in the sidebar
  2. Review the changes
  3. On a review project, make sure the approval card reads Approved — ready to merge
  4. Click Approve 1 change (or Approve N changes)
  5. The branch is merged into contentrain and your main branch is advanced
  6. The feature branch is deleted
  7. A success toast confirms the merge ("Change merged"), or warns you if a pull request into your main branch is still needed

From the Chat ​

Ask the agent to merge a branch:

"Merge the branch cr/content/blog-posts/en/1774800862-27c1"

Or more generally:

"Merge all pending branches"
"List branches and merge the latest one"

On a review project the agent's merge follows the same approval rules as the button. It cannot approve a change itself.

Merge Conflicts ​

If a merge conflict occurs (another process modified the same files), Studio will report the conflict. You can resolve it by:

  1. Rejecting the conflicting branch
  2. Making the changes again (which creates a new branch with the latest base)

WARNING

Studio cannot automatically resolve merge conflicts. If a conflict is detected, the merge will fail and you will see a message indicating that manual resolution on GitHub is needed.

Rejecting Changes ​

To discard changes on a branch:

From the UI ​

  1. Open the review panel
  2. Click Reject, then click again to confirm ("Discard N changes?")
  3. The branch is deleted
  4. No changes are applied to your repository

From the Chat ​

"Reject the branch cr/content/blog-posts/en/1774800862-27c1"

TIP

Rejecting a branch is non-destructive to your existing content. It simply discards the proposed changes by deleting the feature branch.

Branch Health ​

Studio monitors branch health to keep your repository clean. The count that matters is unmerged cr/* branches:

Unmerged branchesStatusEffect
0-49OKWrites proceed
50-79WarningWrites proceed, and you are alerted
80 or moreBlockedNew writes are rejected until you merge or reject existing branches

The two limits can be changed in the project's .contentrain/config.json with branchWarnLimit and branchBlockLimit. You can also ask the AI agent for the branch health (the branch_health tool).

Branch Cleanup ​

Merged cr/* branches that are still around are deleted automatically once they are older than 30 days. Studio runs this check every six hours for every project; there is nothing to confirm. Owners and admins can also trigger it by hand with POST /api/workspaces/{workspaceId}/projects/{projectId}/branches/cleanup.

TIP

Regularly reviewing and merging or rejecting branches keeps your project healthy. A large number of pending branches can indicate bottlenecks in your content workflow.

Branch Naming Convention ​

Understanding branch names helps you identify what changed:

cr/content/blog-posts/en/1774800862-27c1
│  │       │          │  │
│  │       │          │  └─ Timestamp + suffix (unique ID)
│  │       │          └─── Locale
│  │       └────────────── Model ID (target)
│  └────────────────────── Scope (content, model, new, config, media, ...)
└───────────────────────── Contentrain prefix

Permissions ​

Branch operations respect your role:

RoleView BranchesApprove / MergeRejectRequest changes
OwnerYesYesYesYes
AdminYesYesYesYes
EditorYesNoNoNo
ReviewerYesYesYesYes
ViewerYesNoNoNo

Mark addressed is open to anyone who can see the branch. Triggering branch cleanup by hand is limited to owners and admins. A policy can narrow who may approve with roles. The Reviewer and Viewer roles are Enterprise Edition roles; see Team Management.

Next Steps ​

Released under the AGPL-3.0 License. Privacy