Skip to content
GitmoapAPIBeta
Codecommits
POST/repositories/{repo_id}/commits

Commit file changes to a branch

create_commit
  • commit:create
    A token needs the commit:create scope: Write commits from file changes, and resolve merge-request conflictsGranted by write_api, write_repository.Every operation this scope unlocks
  • Audited · mutation

    x-gitmoap-audit: {"kind":"audited","arg":"mutation"}

  • Quota · namespace storage

    x-gitmoap-quota: {"kind":"enforced","arg":"namespace_storage"}

  • Dry run
    Takes dry_run.

One commit from a list of file changes — create, update, delete, move, change the mode — landed through the same branch rules and push rules as a git push. Every change to an existing file names the blob it was made against, so a file changed by someone else meanwhile is refused rather than overwritten. dry_run=true answers what the commit would do and writes nothing.

Parameters

Path
  • repo_idRepositoryId (string · uuid)Repository ID
Query
  • dry_runbooleanoptionalSay what the commit would do — every refusal, the files that changed since they were read, the pipelines it would start — and write nothing

Request body

application/json
  • actionsarray of FileActionThe file changes, at most 100, each path touched once.
  • branchBranchName (string)The branch the commit lands on.
  • messageCommitMessage (string)The commit message, taken as written — trailers such as Signed-off-by included.
  • expected_head_shaCommitHash (string) or nulloptionalThe head the commit must land on. Omitted, the commit lands on the branch's current head as long as every file it changes is still the one the caller edited.
  • start_branchBranchName (string) or nulloptionalCreate branch from this branch's head and land the commit on it, in one step. branch must not exist yet.
Request body exampleSynthesized example
{
"actions": [
{
"action": "create",
"content": "content-c7e2",
"path": "path-f5d1"
}
],
"branch": "feat/run-header-stream",
"message": "Inline scalar newtypes but keep their brand"
}

Responses

200A preview: what the commit would do. Nothing was writtenapplication/json
  • allowedbooleanWhether the commit, sent as it is, would land.
  • authorCommitAuthor
  • branch_existsbooleanWhether branch exists. With start_branch, false means it will be created.
  • pipelinesarray of PredictedPipelineThe pipelines this commit would start, as the branch's push triggers stand now.
    • The PredictedPipeline schema
    • namestring
    • pipeline_idPipelineId (string · uuid) or nulloptionalThe pipeline, when it is one stored in the platform. A pipeline declared in a file under .gitmoap/pipelines/ has no id and is named by its file.
  • refusalsarray of RefusalEvery reason the commit would be refused, each on the field it is about.
    • The Refusal schema
    • codeRefusalCodePERMISSION_REQUIREDBRANCH_PROTECTEDAGENT_REFFOREIGN_AUTHORPRIVILEGED_PATHBRANCH_NOT_FOUNDSTART_BRANCH_NOT_FOUNDFILE_NOT_FOUNDREPOSITORY_EMPTYMR_NOT_OPENNOT_CONFLICTEDHEAD_MOVEDBRANCH_EXISTSFILE_CHANGEDFILE_EXISTSPATH_CONFLICTUNSUPPORTED_ENTRYNOTHING_TO_COMMITUNRESOLVEDNOT_IN_CONFLICTUNSUPPORTED_CONFLICTPUSH_RULE_VIOLATIONWhat kind of refusal this is. Closed: a client branches on it. The wire spelling is the SCREAMING_SNAKE domain code that leads an error's message, so a refusal returned as data and the same refusal returned as an error read the same.
    • messagestringWhat is wrong, in a sentence a person can act on.
    • fieldstring or nulloptionalThe part of the request the refusal is about: message, branch, or actions[i] for the i-th file change.
    • rulestring or nulloptionalThe push rule that refused, by its setting's name (require_issue_reference), when code is PUSH_RULE_VIOLATION.
  • stalearray of StaleFileThe files that changed since the caller read them.
    • The StaleFile schema
    • pathstring
    • current_blob_shaObjectId (string) or nulloptionalThe blob at the branch's head now. Absent when the file has been deleted.
    • last_commitCommitSummary or nulloptionalThe commit that last changed the file, when it was found in time.
      • The CommitSummary schema
      • author_namestringThe author's name as recorded in the commit — a git identity, not a gitmoap account.
      • authored_atstringWhen the change was written, ISO 8601.
      • committed_atstringWhen the commit was created, ISO 8601. Later than authored_at after a rebase or a cherry-pick; this is the time a "last updated" column should show.
      • shaCommitHash (string)The full commit SHA.
      • short_shaShortCommitHash (string)The abbreviated SHA, as git chose to abbreviate it in this repository.
      • titlestringThe commit message's first line.
      • author_avatar_urlstring or nulloptionalThe author's avatar, when this instance serves avatars.
      • author_emailEmail (string) or nulloptionalThe author's email as recorded in the commit. Absent when the commit records something that is not an email address; the commit still has its name and message, only no avatar.
  • head_shaCommitHash (string) or nulloptionalThe head the commit would land on; absent for a repository's first commit.
200 exampleSynthesized example
{
"allowed": false,
"author": {
"email": "tomas@acme.example",
"name": "payments-api"
},
"branch_exists": false,
"pipelines": [
{
"name": "payments-api"
},
{
"name": "payments-api"
}
],
"refusals": [
{
"code": "PERMISSION_REQUIRED",
"message": "Label every synthesized example"
},
{
"code": "PERMISSION_REQUIRED",
"message": "Pin a page's payload to the build that rendered it"
}
],
"stale": [
{
"path": "path-d878"
}
],
"head_sha": "937a776bb9c236ba847bdf0cd91b8799374fd488"
}
201The commit landedapplication/json
  • branchRepositoryBranch
    • The RepositoryBranch schema
    • aheadinteger · int320–∞
    • behindinteger · int320–∞
    • branch_nameBranchName (string)
    • commitCommit
      • The Commit schema
      • author_emailEmail (string)
      • author_namestring
      • authored_atstring
      • commit_shaCommitHash (string)
      • committed_atstring
      • committer_emailEmail (string)
      • committer_namestring
      • repository_idRepositoryId (string · uuid)
      • short_shaShortCommitHash (string)
      • titlestring
      • author_avatar_urlstring or nulloptional
      • committer_avatar_urlstring or nulloptional
      • messagestring or nulloptional
      • parent_shasarray of CommitHash (string)optional
      • tagsarray of TagName (string)optional
    • open_merge_requestsarray of BranchMergeRequestRefThe open merge requests proposing this branch — one per target branch at most. A commit to the branch updates each of them.
      • The BranchMergeRequestRef schema
      • iidMergeRequestId (integer · int64)The merge request's number in its repository.
      • target_branchBranchName (string)Where it proposes to merge the branch.
    • protectedbooleanA branch rule protects this branch.
    • repository_idRepositoryId (string · uuid)
    • viewer_can_pushbooleanWhether the caller may push to this branch — the same verdict a git push or a commit written in the browser gets. false for someone not signed in.
    • push_refusalstring or nulloptionalWhy the caller may not push here, in a sentence to show them. Absent when they may.
  • branch_createdbooleanThe commit created branch (from start_branch, or as a repository's first commit).
  • commitCommit
    • The Commit schema
    • author_emailEmail (string)
    • author_namestring
    • authored_atstring
    • commit_shaCommitHash (string)
    • committed_atstring
    • committer_emailEmail (string)
    • committer_namestring
    • repository_idRepositoryId (string · uuid)
    • short_shaShortCommitHash (string)
    • titlestring
    • author_avatar_urlstring or nulloptional
    • committer_avatar_urlstring or nulloptional
    • messagestring or nulloptional
    • parent_shasarray of CommitHash (string)optional
    • tagsarray of TagName (string)optional
201 exampleSynthesized example
{
"branch": {
"ahead": 5,
"behind": 6,
"branch_name": "refactor/brand-inline",
"commit": {
"author_email": "tomas@acme.example",
"author_name": "Tomás Reyes",
"authored_at": "2026-10-15T15:39:00Z",
"commit_sha": "94f4bacc0c6f0b99d779324910036817bc42d2f5",
"committed_at": "2026-10-13T17:30:12Z",
"committer_email": "tomas@acme.example",
"committer_name": "payments-api",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"short_sha": "340876a61e3410af1cbccbcb14c1b4a64d7a827d",
"title": "Pin a page's payload to the build that rendered it",
"author_avatar_url": "https://gitmoap.example/acme/1443d9eb",
"committer_avatar_url": "https://gitmoap.example/acme/22da5cf2",
"message": "Stream pipeline status into the run header",
"parent_shas": [
"beec518cbb2238afcbc15c751ce053d981ab2b9b",
"b1cfdb61a0f3d31b93ca3159da63199430641fa4"
],
"tags": [
"tags-0e81",
"tags-a2b3"
]
},
"open_merge_requests": [
{
"iid": 42,
"target_branch": "main"
}
],
"protected": false,
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"viewer_can_push": false,
"push_refusal": "push-refusal-7011"
},
"branch_created": false,
"commit": {
"author_email": "mara@acme.example",
"author_name": "Tomás Reyes",
"authored_at": "2026-10-11T19:59:21Z",
"commit_sha": "23ff0453958a83b8695591c8dfa32f7d657c1351",
"committed_at": "2026-10-11T18:27:10Z",
"committer_email": "lin@acme.example",
"committer_name": "payments-api",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"short_sha": "c49cc49e571f1b247ed9a6d69d73e9fb21923257",
"title": "Stream pipeline status into the run header",
"author_avatar_url": "https://gitmoap.example/acme/3c668683",
"committer_avatar_url": "https://gitmoap.example/acme/ba9cdba6",
"message": "Inline scalar newtypes but keep their brand",
"parent_shas": [
"64e80150bf3454cd202cee3fd4bf1ea34014702a",
"663591f99ab56bb32f587a08f924eef7f2cb159f"
],
"tags": [
"tags-9fdd"
]
}
}
400Malformed request: an invalid path, a path changed twice, more than 100 changes, content that is not valid base64application/json
Error codes
  • BAD_REQUESTThe request is malformed: a parameter or a body field is not a well-formed value of its type
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
400 exampleSynthesized example
{
"error": {
"code": "code-4ca7",
"message": "Draw the region map from operation density"
}
}
401Unauthenticated — no credential, or an invalid oneapplication/json
Error codes
  • UNAUTHORIZEDNo credential was sent, or the one sent is invalid, expired or revoked
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
401 exampleSynthesized example
{
"error": {
"code": "code-960e",
"message": "Inline scalar newtypes but keep their brand"
}
}
403The caller may not push to this repository, or a branch rule protects the branchapplication/json
Error codes
  • BRANCH_PROTECTEDA branch rule keeps you from changing this branch this way
  • FORBIDDENYou are signed in but may not do this here; reason names the permission or the rule that refused it
  • INSUFFICIENT_SCOPEThe access token lacks the scope this operation needs; required_scope names it
  • PERMISSION_REQUIREDYou need a permission you do not hold here; the message names it
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
403 exampleSynthesized example
{
"error": {
"code": "code-f94d",
"message": "Pin a page's payload to the build that rendered it"
}
}
404Repository not found, or the branch, the start branch or a file the commit changes does not existapplication/json
Error codes
  • BRANCH_NOT_FOUNDThe branch does not exist, and nothing asked for it to be created
  • FILE_NOT_FOUNDA file the change updates, moves or deletes is not there
  • NOT_FOUNDThe resource does not exist — or exists and you cannot see it: a private resource you have no access to answers exactly as an absent one does
  • START_BRANCH_NOT_FOUNDThe branch a new branch was to start from does not exist
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
404 exampleSynthesized example
{
"error": {
"code": "code-c20e",
"message": "Label every synthesized example"
}
}
409A file changed since it was read, already exists or collides with a directory; the branch moved or already exists; or the repository is empty and the branch is not its defaultapplication/json
Error codes
  • BRANCH_EXISTSA branch with that name already exists
  • CONFLICTThe request conflicts with the resource's current state; reason says how
  • FILE_CHANGEDA file the change edits is no longer the version you read
  • FILE_EXISTSA file the change creates already exists
  • HEAD_MOVEDThe branch moved since you read it; read it again and retry
  • LEGAL_ACCEPTANCE_REQUIREDAccept the current Terms of Service before changing anything; reading stays open
  • PATH_CONFLICTA path collides with the tree: a file where a directory is, or beneath a file
  • REPOSITORY_EMPTYThe repository has no branches or tags yet; there is nothing to read until something is pushed to it
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
409 exampleSynthesized example
{
"error": {
"code": "code-24a6",
"message": "Stream pipeline status into the run header"
}
}
413The request is larger than 16 MiBapplication/json
Error codes
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
413 exampleSynthesized example
{
"error": {
"code": "code-235f",
"message": "Inline scalar newtypes but keep their brand"
}
}
422A push rule refuses the commit, a change targets a symbolic link, a submodule or a directory, or nothing would changeapplication/json
Error codes
  • NOTHING_TO_COMMITThe change leaves every file as it was
  • PUSH_RULE_VIOLATIONA push rule refuses the change; rule names it
  • UNPROCESSABLE_ENTITYThe request is well-formed but asks for something the resource's rules do not allow; reason says which
  • UNSUPPORTED_ENTRYThe entry is a symbolic link, a submodule or a directory, which a commit written in the browser does not change
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
422 exampleSynthesized example
{
"error": {
"code": "code-9f2f",
"message": "Inline scalar newtypes but keep their brand"
}
}
429The commit would take the namespace over its storage limit, or exceeds the per-push sizeapplication/json
Error codes
  • TOO_MANY_REQUESTSRetryableA quota, a rate limit or a transfer budget is spent. When the response carries Retry-After, retry after that many seconds
  • errorErrorBody
    • The ErrorBody schema
    • codestringThe coarse category, tied to the status: NOT_FOUND, CONFLICT, INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all.
    • messagestringWhat went wrong, for a person. Written to be read, not parsed: match on reason or code.
    • fieldstring or nulloptionalOn a 400 that refused one field's value, the field, as its JSON path: email, items[0].name. Put the message under that input. Absent on every other error.
    • reasonstring or nulloptionalThe specific code, when the error has one: LAST_ORGANIZATION_OWNER, BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and on code otherwise.
    • required_scopestring or nulloptionalThe scope the access token was missing, on INSUFFICIENT_SCOPE.
    • violationsanyoptionalPresent on the structured-validation errors (PROVIDER_VALIDATION_FAILED per-node, PIPELINE_VALIDATION_FAILED DAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
429 exampleSynthesized example
{
"error": {
"code": "code-7a94",
"message": "Label every synthesized example"
}
}

CLI

gitmoap commits create

  • --repo-ididRepository ID (id or owner/repo path)
  • --dry-runflagoptionalSay what the commit would do — every refusal, the files that changed since they were read, the pipelines it would start — and write nothing
  • --actionsjsonThe file changes, at most 100, each path touched once.
  • --branchstringThe branch the commit lands on.
  • --expected-head-shastringoptional
  • --messagestringThe commit message, taken as written — trailers such as `Signed-off-by` included.
  • --start-branchstringoptional

Used in these guides