# Cherry-pick one change

Cherry-pick applies one ordinary accepted change from another branch in the same
repository. Use it to backport a crash fix to a release branch without taking an
unfinished feature, or bring a shared engine correction into a customized engine
branch. A mount pin can then point the parent project at the resulting engine
revision. First finish and submit the pick inside the child workspace. Then
publish the parent pin, either with `scribe project update` followed by `submit`,
or with `scribe project publish` from the parent. Project publication requires
finished child resolution workflows; it cannot submit an active cherry-pick for you.

## Example: backport a fix

Suppose `development` has change 40 (an unfinished renderer) and change 42
(a crash fix). The release branch should receive only the delta introduced by 42:

```sh
scribe switch release
scribe cherry-pick 42 --from development
scribe status
# Review the resulting files in your editor before submitting.
scribe submit -m "Backport crash fix from development change 42"
```

`--from` must name the branch that accepted the change. A branch's history also
reaches back through its origin into the branch it forked from, but selecting
one of those inherited revisions is refused with `change_not_found` naming the
branch to pick it from: recorded provenance identifies where the change was
accepted, not which branch was asked for it. Select its accepting branch instead;
the ordinary source-type, target, and permission checks still apply.

The source delta is the selected commit compared with its immediate first parent.
It does not include every earlier source change. A fix that depends on earlier
work may need that work selected separately; conflict-free application does not
prove the program builds or behaves correctly. Run the project's checks before
submitting.

Full and partial working copies are supported;
[partial-view integration](/docs/partial-view-merging.md) explains excluded changes and
conflicts. Submit or revert opened files and complete pending sync before starting.
Unopened modifications to affected files prevent application;
unrelated local edits are preserved. Explicit moves use the native rename-aware
resolver. Repository lock rules apply across branches as usual: planning refuses
a pick over a path another workspace holds and acquires the locks the policy
requires for the paths it rewrites, which `cherry-pick --abort` then releases.
See [locks in merging](/docs/branches.md).

## Conflicts, interruption, and abort

Non-overlapping UTF-8 text edits inside the view are merged automatically by the
CLI. Overlapping text, binary content, deletion conflicts and ambiguous renames
need a decision:

```sh
scribe resolve
scribe resolve --theirs Assets/material.bin
scribe resolve --ours Source/local-settings.cpp
# Edit a conflicted text file, then mark that complete result:
scribe resolve --working Source/crash.cpp
scribe cherry-pick --continue
scribe status
scribe submit -m "Backport crash fix with release-specific resolution"
```

`--ours` keeps the target result; `--theirs` takes the selected source result,
including deletion. Keeping a different target result is submitted as an explicit
keep decision, so the pick still accounts for the source change. Included paths
appear in `scribe status` opened for `keep` until submission; excluded decisions
remain in the resolution journal without opening local files. Use the resolver's
group choices for structural/rename conflicts.
`scribe cherry-pick --continue` resumes the saved source and target revisions; it
does not silently pick a newer source head. `scribe cherry-pick --abort` abandons
an unsubmitted pick, restores its target baseline and saves displaced edits in
`.scribe/_state/recovery`. It cannot undo an accepted commit.

If the target advances before submission, acceptance rejects the stale target.
For a full-view, ungrouped plan, use `scribe resolve --update` and resolve against
the new target. Partial-view plans and rename/collision groups require aborting
and restarting; preserve manual resolutions you want to reuse. If a submission
outcome is unknown, repeat `scribe submit -m "the original message"` to resolve the
saved operation before changing or abandoning it. Never generate a new operation
merely because the connection failed.

## History and repeated picks

A successful pick is one new commit on the target. `scribe log` and JSON history
show the accepting source branch ID and change number as `cherry_pick`. This is provenance
of the selected intent, not a second parent or proof that every source byte won a
conflict. Choosing the target result for every file still creates a provenance-only
commit. The original accepted source remains unchanged.

A source already in the target's ancestry, or already recorded as picked by a
true ancestor, is reported as already applied. This includes picks inherited by
new branches and through full merges. A competing duplicate publication is rejected
with a durable outcome. Reverting file contents does not erase the recorded pick.

A later `scribe merge development` still considers the unpicked work. Picks never
add merge ancestry; a subsequent full merge can need conflict resolution even when
some source changes were selected earlier. Merge commits and cherry-pick commits
are not supported as sources. Choose the original ordinary change. Changes cannot
be selected across repositories, and a pick does not create a fork. Ancestry checks
are bounded to 100,000 visited commits.

## Web interface

Open repository **History**, choose **Cherry-pick** on an ordinary change, select
another target branch, then **Preview changes**. The preview pins the current target
head and shows every affected path with before-source, target and source links.
**Compare file contents** loads text previews. Unchanged-side cases receive a default
choice; when both sides changed, choose **Use source**, **Keep target**, or enter the
complete resolved UTF-8 text. The web editor requires explicit resolution in those
cases; the CLI also provides automatic non-overlapping text merging.

The web/SDK preview supports up to 128 affected paths and directs renamed-file
cases, including affected base files absent from the target, to the CLI. Binary files can be selected without downloading their bytes.
Edited text is limited to 512 KiB per file and 2 MiB total. Source/target selection
can refer to larger binary objects because their accepted manifests are reused.
Storage still enforces path collisions, live permissions, lock policy and the pinned
target head. Mount declarations are ordinary `.scribe/config.toml` edits and retain
all normal configuration checks and mounted-repository permission boundaries.

Only writers see the history action. Read permission suffices for the authenticated
preview API; publishing needs write permission, and changing lock policy needs the
existing elevated permission. The exact operation and resolutions are saved before
transmission. If a response is lost, use the same dialog retry or **Saved submissions**.
Saved submissions are scoped to the account and namespace. A rejected operation
must be dismissed and reviewed again with a new preview before making a new request.

## TypeScript SDK and HTTP API

```ts
const plan = await client.cherryPickPlan("orbit-engine", {
  branch: "release", revision: "38", source: "development", change: "42",
});
const intent = await client.prepareCherryPick("orbit-engine", {
  branch: plan.target.id, revision: plan.target.head,
  source: plan.source.id, change: plan.source.head,
  message: "Backport crash fix",
  resolutions: [{ path: "Assets/material.bin", choice: "target" }],
}, operationId); // native operation ID: 32 lowercase hex characters, not all zero, generated once
// Durably persist the complete intent before this call.
const outcome = await client.submitCommit(intent);
// After uncertainty, resolve/retry this exact intent; never replace its operation ID.
const known = await client.operationOutcome(intent);
```

`resolutions` can omit paths with automatic choices but must resolve every conflict.
Unknown or duplicate paths are refused. Do not submit when `plan.alreadyApplied` is
true. `prepareCherryPick` rechecks the pinned target before freezing object bytes.

Authenticated HTTP routes under `/api/v1`:

- `POST /repositories/:repo/cherry-picks/preview`: `{branch, revision, source, change}`.
- `POST /repositories/:repo/cherry-picks`: the selection plus `action: "cherry-pick"`,
  a UUID `operationId`, `message`, and `resolutions`. The UUID identifies the HTTP
  request; the API generates and persists its own native operation ID for it.
- `GET /operations/:id`: resolve the same saved operation, shared with file commits.

Browser writes retain the existing origin/CSRF checks. Automation tokens need
`contents:read` for preview and `contents:write` for submission and outcome lookup.
Responses use the existing accepted/rejected/pending commit result contract. The API
persists its native operation ID and exact prepared objects before any native writes;
clients must persist the HTTP request before sending it as well.
