Skip to content
GitmoapAPIBeta
Codediffs
GET/repositories/{repo_id}/compare

Compare two branches

compare_refs
  • diff:read
    A token needs the diff:read scope: View commit, merge-request, and branch-comparison diffsGranted by mcp_agent, mcp_agent_write, read_api, read_repository, write_api, write_repository.Every operation this scope unlocks
  • Metered egress · in band body

    x-gitmoap-egress: {"kind":"metered","arg":"in_band_body"}

  • Cacheable · derived SHA artifact

    x-gitmoap-cache: {"kind":"derived_sha_artifact"}

How far head is ahead of and behind base, up to 100 of the commits head adds (newest first), and the diff of head against the commit where it left base; branches with no common history are compared directly. Both must be branches of the repository. The diff pages like the other diffs.

Parameters

Path
  • repo_idRepositoryId (string · uuid)Repository ID
Query
  • basestringBase (target) branch. Required.
  • headstringHead (source) branch. Required.
  • pageintegeroptionalFile-diff page number (0-based). Default: 0
  • limitintegeroptionalFiles per page (1-100). Default: 20
  • include_patchbooleanoptionalInclude unified diff patch content. Default: false
  • collapsebooleanoptionalAuto-collapse generated/oversized file patches (fetch them via /diff-file). Default: true

Responses

200Branch comparisonapplication/json
  • aheadinteger · int320–∞Commits on head not on base.
  • base_shaCommitHash (string)Tip commit of the base (target) branch.
  • behindinteger · int320–∞Commits on base not on head.
  • commitsarray of CommitBounded, newest-first preview of the commits head adds over base.
    • 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
  • commits_truncatedbooleantrue when there are more commits than the preview cap returned.
  • diffDiffResponseThree-dot file diff. Note diff.base_sha is the merge base (or the base tip when histories are unrelated), not CompareResponse.base_sha.
    • The DiffResponse schema
    • base_shaCommitHash (string)
    • filesarray of DiffFile
      • The DiffFile schema
      • additionsinteger0–∞
      • collapsedbooleanThe patch was intentionally withheld (generated or oversized) to save bytes but is fetchable in full on demand via GET .../diff-file. Only ever set when patches were requested (include_patch=true).
      • deletionsinteger0–∞
      • generatedbooleanDetected generated/lock/minified file. Always computed from the path, independent of collapsed, so a client can badge or auto-fold it.
      • is_binaryboolean
      • patch_truncatedbooleanThe patch exceeds the hard per-file size cap and is omitted. Unlike collapsed, this file is not expandable in place — a client reads it piece-by-piece via GET .../file-lines instead.
      • pathstring
      • statusDiffFileStatusaddedmodifieddeletedrenamedcopied
      • collapse_reasonCollapseReasongeneratedlargeor nulloptionalWhy a file's patch body was withheld from a DiffFile (see collapsed). Distinct from patch_truncated, which marks a patch too large to ever send; a collapsed file's patch is fetchable on demand via GET .../diff-file.
      • old_pathstring or nulloptional
      • patchstring or nulloptional
    • has_morebooleanAnother page follows this one.
    • head_shaCommitHash (string)
    • pageinteger0–∞The page returned, from 0.
    • statsDiffStats
      • The DiffStats schema
      • additionsinteger0–∞Lines added across the whole change.
      • deletionsinteger0–∞Lines deleted across the whole change.
      • files_changedinteger0–∞Every file the change touches.
    • total_filesinteger0–∞How many files the pages can reach — every changed file, unless truncated.
    • truncatedbooleanThe change touches more files than any page can reach. stats still counts all of them.
  • head_shaCommitHash (string)Tip commit of the head (source) branch.
  • total_commitsinteger · int320–∞Total commits the comparison contains (== ahead, uncapped).
  • merge_base_shaCommitHash (string) or nulloptionalCommon ancestor of base and head. null when the two branches have unrelated histories (no common ancestor); the diff then degrades to a direct two-dot comparison against the base tip.
200 exampleSynthesized example
{
"ahead": 3,
"base_sha": "39350e39a4211c74666321c78af2faf11813117c",
"behind": 0,
"commits": [
{
"author_email": "lin@acme.example",
"author_name": "Tomás Reyes",
"authored_at": "2026-10-15T14:45:47Z",
"commit_sha": "908c4552abfa324f0ca1ba83fd0bd9b406671227",
"committed_at": "2026-10-09T21:43:57Z",
"committer_email": "mara@acme.example",
"committer_name": "payments-api",
"repository_id": "5b0e7c2a-9d14-4e8b-a6f1-2c3d4e5f6a70",
"short_sha": "131b09cdd8268baba099f1b27ebb5bd516946577",
"title": "Inline scalar newtypes but keep their brand"
}
],
"commits_truncated": false,
"diff": {
"base_sha": "5e7f5e983cbd453b180fdeef6f92e8560d33b657",
"files": [
{
"additions": 16,
"collapsed": false,
"deletions": 45,
"generated": false,
"is_binary": false,
"patch_truncated": false,
"path": "path-9a2b",
"status": "added"
}
],
"has_more": false,
"head_sha": "c3bf756f73ade4cbe4c6db3378f6d05df7405cba",
"page": 69,
"stats": {
"additions": 66,
"deletions": 89,
"files_changed": 4
},
"total_files": 4,
"truncated": false
},
"head_sha": "52e5f4874fbc2f6aea3776e0864caa469f25a9ee",
"total_commits": 3,
"merge_base_sha": "9e5403af485c609b18d94edfc62097dabe64028f"
}
400Missing or invalid base/head branchapplication/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-3873",
"message": "Pin a page's payload to the build that rendered it"
}
}
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-4b93",
"message": "Stream pipeline status into the run header"
}
}
403Forbidden — the caller's access level or token scope is insufficientapplication/json
Error codes
  • 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-58f1",
"message": "Stream pipeline status into the run header"
}
}
404Repository or branch not foundapplication/json
Error codes
  • 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
  • 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-b406",
"message": "Stream pipeline status into the run header"
}
}

CLI

gitmoap diffs compare-refs

  • --repo-ididRepository ID (id or owner/repo path)
  • --basestringBase (target) branch. Required.
  • --collapseflagoptionalAuto-collapse generated/oversized file patches (fetch them via /diff-file). Default: true
  • --headstringHead (source) branch. Required.
  • --include-patchflagoptionalInclude unified diff patch content. Default: false
  • --limitnumberoptionalFiles per page (1-100). Default: 20
  • --pagenumberoptionalFile-diff page number (0-based). Default: 0

Used in these guides