# Branching

Scribase branching gives every developer, feature branch, and pull request its
own database that forks from production in under a second. Branches are cheap,
isolated, and disposable.

## Local branches

Local branches use copy-on-write Postgres snapshots inside `.scribase/`.

```sh
# Create a branch from the primary
scribase branch new my-feature

# Connect to it
psql "$(scribase branch url my-feature)"

# List all branches
scribase branch list

# Delete when done
scribase branch delete my-feature
```

Copy-on-write means: only the pages you write are copied. A branch that makes
a small schema change uses almost no extra disk space.

## Remote branches (control-plane)

Remote branches are registered environments linked to a parent for schema
diffing and merging. They are the building block for pull-request preview
environments.

### PR preview workflow

```sh
# 1. Provision a preview environment
scribase env create acme store pr-42 preview schema-only us-east create-pr-42 72

# 2. Register it as a branch of production
scribase branch register acme store pr-42 --base production

# 3. Link it to the GitHub PR
scribase branch pr acme store pr-42 github acme/store 42

# 4. Apply the branch's migrations
scribase migrate acme store pr-42 --dir ./migrations --apply

# 5. Review the schema diff
scribase branch diff acme store production pr-42

# 6. Merge on approval
scribase branch merge acme store production pr-42
```

## Branch data modes

When creating a preview environment, choose a data mode:

| Mode | Description |
|---|---|
| `schema-only` | Empty database with production schema applied |
| `snapshot` | Cloned from the latest production backup |
| `empty` | Completely blank Postgres instance |

`schema-only` is the fastest and most common for PR previews. `snapshot` is
better when tests need realistic data.

## TTL (time-to-live)

Preview environments can be auto-deleted after N hours:

```sh
scribase env create acme store pr-42 preview schema-only us-east create-pr-42 72
#                                                                               ^^ 72-hour TTL
```

When the TTL expires, the operator's reconcile loop (the `worker` service) claims the preview and deletes it through the same audited delete operation as `scribase env delete`. Extend a preview before it expires with `scribase env renew`.

## Merge conflict resolution

A three-way merge compares the base environment's schema at registration time
(the merge base), the current base (production), and the head (the branch).

- **No conflict**: the changes apply cleanly.
- **Conflict**: both sides modified the same object. Use `--force` to have the
  head win, or resolve manually.

```sh
scribase branch merge acme store production pr-42 --force
```

## Schema diff output

`branch diff` returns a list of changed objects:

```json
{
  "changes": [
    { "kind": "table", "name": "payments", "action": "added" },
    { "kind": "column", "table": "orders", "name": "paid_at", "action": "added" },
    { "kind": "policy", "table": "payments", "name": "owner can read", "action": "added" }
  ]
}
```

## Best practices

- Create one branch per feature or PR, not per developer.
- Use `schema-only` mode for CI test branches to avoid copying production data.
- Set a short TTL (24–72 hours) on preview environments to avoid accumulating
  stale branches.
- Always run `branch diff` before merging to review what changed.
- Run `schema test` against the branch before merging to catch policy regressions.
