> ## Documentation Index
> Fetch the complete documentation index at: https://code.storage/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# repo.merge()

> Merge one branch into another with merge, fast-forward-only, or fast-forward-preferred behavior.

> [!WARNING]
>
> This page documents the earlier Code Storage SDKs: `@pierre/storage`, `pierre-storage`, and
> `code-storage-go`. New code uses the [Pierre SDK](https://code.storage/docs/sdks.md). To move code to the new SDK, use the
> [`pierre-migrate`
> skill](https://github.com/pierrecomputer/skills/tree/main/skills/pierre-migrate).

```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
const result = await repo.merge({
  sourceBranch: 'feature/preview',
  sourceIsEphemeral: true,
  targetBranch: 'main',
  targetIsEphemeral: false,
  expectedTargetSha: currentMainSha, // optional optimistic concurrency guard
  strategy: 'merge', // "merge" | "ff_only" | "ff_prefer"
  commitMessage: 'Merge feature/preview', // optional
  author: { name: 'Merge Bot', email: 'merge@example.com' }, // optional
  committer: { name: 'Merge Bot', email: 'merge@example.com' }, // optional
  allowUnrelatedHistories: false, // optional
  squash: false, // optional, incompatible with "ff_only"
});

console.log(result.result); // "merge_commit", "fast_forward", "no_op", or "unknown"
console.log(result.target.oldSha);
console.log(result.target.newSha);
```

```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
result = await repo.merge(
    source_branch="feature/preview",
    source_is_ephemeral=True,
    target_branch="main",
    target_is_ephemeral=False,
    expected_target_sha=current_main_sha,
    strategy="merge",
    commit_message="Merge feature/preview",
    author={"name": "Merge Bot", "email": "merge@example.com"},
    committer={"name": "Merge Bot", "email": "merge@example.com"},
    allow_unrelated_histories=False,
    squash=False,  # optional, incompatible with "ff_only"
)

print(result["result"])  # "merge_commit", "fast_forward", "no_op", "squash", or "unknown"
print(result["target"]["old_sha"])
print(result["target"]["new_sha"])
```

```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
result, err := repo.Merge(context.Background(), storage.MergeOptions{
	SourceBranch:            "feature/preview",
	SourceIsEphemeral:       true,
	TargetBranch:            "main",
	TargetIsEphemeral:       false,
	ExpectedTargetSHA:       currentMainSHA,
	Strategy:                storage.MergeStrategyMerge,
	CommitMessage:           "Merge feature/preview",
	Author:                  &storage.CommitSignature{Name: "Merge Bot", Email: "merge@example.com"},
	Committer:               &storage.CommitSignature{Name: "Merge Bot", Email: "merge@example.com"},
	AllowUnrelatedHistories: false,
	Squash:                  false, // optional, incompatible with MergeStrategyFFOnly
})

fmt.Println(result.Result)
fmt.Println(result.Target.OldSHA)
fmt.Println(result.Target.NewSHA)
```

Source and target branches can independently live in the default or ephemeral namespace. Use
`expectedTargetSha` when you want an optimistic concurrency check before updating the target branch.

## Concurrency behavior

`merge()` has two target-tip modes:

* Provide `expectedTargetSha` when the target branch must still point at a specific commit. If the
  target moved, the merge fails with `409`.
* Omit `expectedTargetSha` when you want Code Storage to merge into the current target tip. For
  native Code Storage targets, the gateway may retry stale target or repository movement internally
  while keeping the originally resolved source commit pinned.

Automatic retry is useful when many workers are merging into the same target branch. Retries do not
chase new source branch commits: once the first merge attempt resolves the source tip, every retry
merges that same source commit against the latest target tip.

> [!NOTE]
>
> Automatic stale-target retry is disabled for GitHub-backed public targets. Those merges use the
> same single-attempt behavior as a strict target-tip guard.

## Options

**sourceBranch** `string` *required*

Source branch name to merge from.

**sourceIsEphemeral** `boolean`

Set to `true` when the source branch lives in the ephemeral namespace.

**targetBranch** `string` *required*

Target branch name to merge into.

**targetIsEphemeral** `boolean`

Set to `true` when the target branch lives in the ephemeral namespace.

**strategy** `string` *required*

Merge strategy. Must be one of `merge`, `ff_only`, or `ff_prefer`.

**expectedTargetSha** `string`

Commit SHA that must match the current target tip before the merge is applied. Providing this
field enables strict optimistic concurrency and disables automatic stale-target retry.

**commitMessage** `string`

Optional merge commit message. Used when the backend creates a merge commit.

**author** `object`

Optional commit identity with `name` and `email`. Required together when provided.

**committer** `object`

Optional committer identity with `name` and `email`. Required together when provided.

**allowUnrelatedHistories** `boolean`

Set to `true` to allow merging branches without a shared history.

**squash** `boolean`

Collapse the source into a single new commit whose only parent is the current target tip.
Incompatible with the `ff_only` strategy.

**refPolicies** `object[]`

Ordered ref policy rules (`{ pattern, ops? }`) in the JWT for this call. Code Storage uses the first rule that matches the target ref. Python: `ref_policies`. Go: `RefPolicies` with type `storage.RefPolicyList`. See [Ref Policies](https://code.storage/docs/repos/ref-policies.md).

## Response

**result** `string`

Merge outcome: `merge_commit`, `fast_forward`, `no_op`, or `unknown`. The Python and Go SDKs also
surface `squash`. The TypeScript SDK normalizes `squash` to `merge_commit` for semver
compatibility.

**commitSha** `string`

Commit SHA reported for the merge result.

**treeSha** `string`

Tree SHA for the resulting commit.

**source** `object`

Source ref metadata with `branch`, `ephemeral`, and `sha`.

**target** `object`

Target ref metadata with `branch`, `ephemeral`, and `oldSha`/`old_sha` plus `newSha`/`new_sha`.

**mergeBaseSha** `string`

Merge base SHA when the backend reports one.

**promotedCommits** `number`

Number of commits promoted onto the target branch.

## Errors

Merge conflicts and retry exhaustion are surfaced as `ApiError`/`APIError`. The raw error body is
preserved, so callers can inspect `conflict_type` and any backend fields included with the response.

```json theme={"theme":{"light":"github-light","dark":"min-dark"}}
{
  "error": "merge conflict",
  "conflict_type": "merge_conflict",
  "conflict_paths": ["docs/example.md"],
  "merge_base_sha": "a2d127e6a4d54bb7390de828a99e36411f0c84df"
}
```

`conflict_type` can be:

* `merge_conflict`: Git found file-level conflicts. `conflict_paths` and `merge_base_sha` may be
  present.
* `target_moved`: the target branch kept moving during automatic retry. Retry the merge later.
* `repo_changed`: repository state changed during automatic retry. Retry the merge later.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.