PIERRE COMPUTER COMPANY █
CODE STORAGE
2026
← Back
------
Feature:

Merge Source Guard

Date:October 22, 2026Author:Nicolas GallagherCategory:ENGINEERING
------

Merges take a new optional field: expected_source_sha. Set it to the source commit that you reviewed. The merge then uses that commit, not the current tip of source_ref.

Without the field, a merge reads the source branch when it starts. If the branch moves after you preview the merge, the merge can include commits that you did not review.

A merge preview returns source_tip_sha and target_tip_sha. Send them as expected_source_sha and expected_target_sha:

curl "$PIERRE_API_BASE_URL/repos/my-repo/merge" \
  -H "Authorization: Bearer $PIERRE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "source_ref": "feature/preview",
    "expected_source_sha": "9eb378bdb5bf1944f6ba0bd5a2c4df3ce32f4df1",
    "target_branch": "main",
    "expected_target_sha": "c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2",
    "strategy": "merge",
    "commit_message": "Merge feature/preview",
    "author": { "name": "Merge Bot", "email": "merge-bot@example.com" }
  }'

If the source branch advances and still contains the commit, the merge uses the commit that you sent. If the branch no longer contains it, for example after a force push or a delete, the merge returns 409 and changes nothing:

{
  "type": "about:blank",
  "title": "Conflict",
  "status": 409,
  "detail": "source branch moved: the source branch does not contain commit 9eb378bdb5bf1944f6ba0bd5a2c4df3ce32f4df1",
  "code": "conflict",
  "error": "source branch moved: the source branch does not contain commit 9eb378bdb5bf1944f6ba0bd5a2c4df3ce32f4df1"
}

The detail of a failed source guard starts with source branch moved:. Use it to tell this failure from the other 409 responses of a merge.

See the API reference for repos.merge and repos.previewMerge.

+ Recently +