neosourceDocs
Search docs

Update a pull request's branch with its target

POST/api/repos/{owner}/{repo}/pulls/{number}/update-branch

updatePullRequestBranch

Brings the pull request's source branch up to date by merging its target branch into it — the inverse direction of a merge. This always produces a **merge commit** (first parent = the old head, second = the target tip) and never a rebase: the pull request's own commits, their change identities and every review-thread anchor are left untouched. Armed auto-merge survives the update, since an update introduces no newly authored content for a reviewer to re-approve. `outcome` is `already_up_to_date` when the target was already contained in the head (nothing is published), or `updated` with the new head. Returns 409 when the merge conflicts, when the branch has no commits of its own (updating it would empty the pull request), when the source branch lives in a fork, or when `expected_head` no longer matches the current head. Requires write access.

Requires authentication using a bearer token or a session cookie — see tokens and scopes.

curl

curl -X POST 'https://neosource.dev/api/repos/OWNER/REPO/pulls/NUMBER/update-branch' \
  -H 'Authorization: Bearer $NEOSOURCE_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{}'

fetch

fetch("https://neosource.dev/api/repos/OWNER/REPO/pulls/NUMBER/update-branch", {
  method: "POST",
  headers: {
    Authorization: "Bearer $NEOSOURCE_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({}),
});

neo

neo pr update-branch NUMBER OWNER/REPO

Path parameters

ownerrequired

Repository owner or organization slug.

string

reporequired

Repository name.

string

numberrequired

Change request number.

integerint32

Request bodyrequired

application/json

UpdateBranchRequest

object

Optional body for `POST .../pulls/{number}/update-branch`. Empty body is allowed (update with no precondition); `{}` and an absent body behave identically.

expected_head

string | null

Expected current head commit (40-char Git OID hex, as returned in `PullRequestResponse::head_commit`). When supplied and it no longer matches the PR's head, the update is rejected with 409 — guards against updating a stale view after a concurrent push to the source branch. The server also accepts the legacy 64-char internal form.

Responses

200Branch updated, or already up to date

application/json

UpdateBranchResponse

object

Result of `POST .../pulls/{number}/update-branch`.

new_head

string | null

The source branch's new head (40-char Git OID hex) — present exactly when `outcome` is `updated`. Rendered with `to_git_hex()` so it matches `PullRequestResponse::head_commit` rather than leaking the internal 32-byte zero-padded form. (No `From<UpdateBranchResult>` impl: that type lives in `neosource-forge`, which this crate deliberately does not depend on — the route handler does the two-field conversion.)

outcomerequired

UpdateBranchOutcome

string

What an "update branch" did to a pull request's SOURCE branch — GitHub's Update-branch button, which merges the PR's target branch *into* its head. Closed set on purpose: the two states are "the target was already contained in the head" and "a merge commit was created and the head advanced onto it". Every other shape (the head has no commits of its own, a content conflict, a head that moved under the caller) is a refusal, not an outcome — see `PullRequestService::update_branch`. There is deliberately no `FastForward`/`Rebase` variant: the update always produces a merge commit, never a rewrite, because rebasing would require the platform to author replacement commits (ADR 0050, unimplemented).

"already_up_to_date""updated"

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 401Authentication required
  • 403Forbidden — one of: forbidden
  • 404Not Found — one of: not_found
  • 409Conflict — one of: already_exists, conflict, non_fast_forward, github_sync_active
  • 423Locked — one of: busy
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget