Skip to content
GitmoapdocsBeta
Guide· How do I…?

Branches

Overview

A branch is a named pointer to a commit, and in Gitmoap it lives in git exactly as it does on your laptop — there is no separate copy of it in a database to fall out of step. You create branches to work on something without disturbing the default branch, open a merge request from one when the work is ready, and delete it once the work has landed.

Everything on this page also works from git itself. The API and the CLI exist for the times when you want to do it without a clone: a script that opens a branch per ticket, a bot that reaps merged branches, a dashboard that lists what is in flight.

Quick start

Quick start2 steps

Start a branch

You’ll need Developer on the repository, and a clone of it.
  1. Create the branch and switch to it:

    git switch -c my-change
  2. Push it and track it. It appears under Branches as soon as the push lands, with how far it is ahead of the default branch.

    git push -u origin my-change

Before you start

  • A repository you can read.Listing and reading branches follows the repository's visibility: a public repository answers anyone, an internal one answers anyone signed in, and a private one answers only its members.
  • Developer access to create a branch, and Developer access to delete one.The same level covers both. What actually raises the bar on a particular branch is a branch rule: a protected pattern can require Maintainer to push to it, and the default branch cannot be deleted at all.
  • A token with the right scope, if you are calling the API or the CLI rather than clicking: branch:read to list and read, branch:create to create, branch:delete to delete. A personal access token carries the scopes you choose when you mint it, so a script that only reads should be given only branch:read.
  • Something to branch from.A new branch starts at a commit that already exists — usually the tip of the default branch.

How to

List the branches in a repository

Each branch comes back with its head commit and how far it is ahead of and behind the default branch, which is the pair of numbers that tells you whether it needs a rebase before it will merge cleanly.

Each also says whether a branch rule protects it, whether you can push to it — with the reason when you cannot, in the same words a push would be refused with — and the open merge requests proposing it. That is what lets an editor offer to commit to a branch only when it would work.

Open the repository and choose Branches in the side navigation. The list shows every branch with its head commit, who pushed it and when, and how far ahead of and behind the default branch it is. Type in the filter box to narrow the list by name; the default branch is pinned to the top and labelled.

Terminalbash
gitmoap branches list --repo-id <id>
curlbash
curl -X GET https://api.gitmoap.example/repositories/{repo_id}/branches \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Create a branch

A branch is created from another branch, which you always name — there is no default. Give the new branch's name and the branch it starts from; the new branch points at whatever that one points at right now.

Open the repository, choose Branches, then New branch. Give the branch a name and pick the branch it starts from — the default branch is preselected. Create branch takes you to the new branch's view.

Terminalbash
gitmoap branches create \
--repo-id <id> \
--branch-name <branch name> \
--from-branch <from branch>
curlbash
curl -X POST https://api.gitmoap.example/repositories/{repo_id}/branches \
-H "Authorization: Bearer $GITMOAP_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "branch_name": "<string>", "from_branch": "<string>" }'

The name has to be a valid git ref — no spaces, no .., no leading or trailing / — and it has to be free. Creating a branch over a name that is taken is refused rather than performed, so you cannot move somebody else's branch by accident. Names like feature/login are ordinary: the / is part of the name, not a directory.

Delete a branch

Warning

Deleting a branch is immediate and cannot be undone through Gitmoap. The commits it pointed at are not deleted straight away, but nothing names them any more, so unless you or somebody else has the commit id written down the work is effectively gone. If the branch has been merged, its commits are reachable from the branch it was merged into and nothing is lost.

Two deletions are refused rather than performed, and both refusals are deliberate:

  • The default branch cannot be deleted. Every repository's default branch is main, fixed when the repository is created, and there is no setting that moves it — so this refusal is permanent rather than something to work around.
  • A branch that an open merge request is merging into cannot be deleted, because the merge request would have nowhere to land. Close or retarget the merge request first.

Deleting a branch that an open merge request is merging from is allowed. The merge request stays, and reports that its source branch is gone — which is what you want when you delete a branch by accident and need to see which work you interrupted.

Open the repository and choose Branches. Find the branch in the list and choose the bin icon at the end of its row. The confirmation names the branch and its head commit; Delete is immediate.

Terminalbash
gitmoap branches delete --repo-id <id> --branch-name <id>
curlbash
curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/branches/{branch_name} \
-H "Authorization: Bearer $GITMOAP_TOKEN"

Reference

4 endpoints

GET/repositories/{repo_id}/branchesbranch:read

List branches in a repository

list_branchesGET /repositories/{repo_id}/branchesOpen in the API reference

Token scope

branch:read

Send

Path
  • repo_iduuidRepository ID
Query
  • limitint32optionalPage size (1-100)
  • next_tokenstringoptionalPagination cursor

Refuses

  • 400An unreadable pagination token, or a malformed repository ID
  • 401Unauthenticated — no credential, or an invalid one
  • 403Forbidden — the caller's access level or token scope is insufficient
  • 404Not found — or found and private, which is masked as absent

Receive

  • items[]object20 fields
    • aheadint32
    • behindint32
    • branch_namestring
    • commitobject13 fields
      • author_avatar_urlobjectoptional
      • author_emailstring
      • author_namestring
      • authored_atstring
      • commit_shastring
      • committed_atstring
      • committer_avatar_urlobjectoptional
      • committer_emailstring
      • committer_namestring
      • messageobjectoptional
      • repository_iduuid
      • short_shastring
      • titlestring
    • protectedbooleanA branch rule protects this branch.
    • push_refusalobjectoptionalWhy the caller may not push here, in a sentence to show them. Absent when they may.
    • repository_iduuid
    • 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.
  • next_tokenobjectoptional
GET/repositories/{repo_id}/branches/{branch_name}branch:read

Get a branch by name

get_branchGET /repositories/{repo_id}/branches/{branch_name}Open in the API reference

Token scope

branch:read

Send

Path
  • repo_iduuidRepository ID
  • branch_namestringBranch name

Refuses

  • 400Bad request — a path parameter is not a well-formed value of its type
  • 401Unauthenticated — no credential, or an invalid one
  • 403Forbidden — the caller's access level or token scope is insufficient
  • 404Branch not found

Receive

  • aheadint32
  • behindint32
  • branch_namestring
  • commitobject13 fields
    • author_avatar_urlobjectoptional
    • author_emailstring
    • author_namestring
    • authored_atstring
    • commit_shastring
    • committed_atstring
    • committer_avatar_urlobjectoptional
    • committer_emailstring
    • committer_namestring
    • messageobjectoptional
    • repository_iduuid
    • short_shastring
    • titlestring
  • open_merge_requests[]object2 fields
    • iidint64
    • target_branchstring
  • protectedbooleanA branch rule protects this branch.
  • push_refusalobjectoptionalWhy the caller may not push here, in a sentence to show them. Absent when they may.
  • repository_iduuid
  • 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.
POST/repositories/{repo_id}/branchesbranch:create

Create a branch in a repository

create_branchPOST /repositories/{repo_id}/branchesOpen in the API reference

Token scope

branch:create

Will count against

branches_per_repo

not enforced today

Send

Path
  • repo_iduuidRepository ID
Body
  • branch_namestring
  • from_branchstring

Refuses

  • 400Invalid request
  • 401Unauthenticated — no credential, or an invalid one
  • 403The caller may not push here, or a branch rule protects this name
  • 404Repository or source branch not found
  • 409A branch with this name already exists
  • 422The name breaks the repository's branch-name push rule

Receive

The same shape get_branch returns — 9 fields. Go to it

Show it here
  • aheadint32
  • behindint32
  • branch_namestring
  • commitobject13 fields
    • author_avatar_urlobjectoptional
    • author_emailstring
    • author_namestring
    • authored_atstring
    • commit_shastring
    • committed_atstring
    • committer_avatar_urlobjectoptional
    • committer_emailstring
    • committer_namestring
    • messageobjectoptional
    • repository_iduuid
    • short_shastring
    • titlestring
  • open_merge_requests[]object2 fields
    • iidint64
    • target_branchstring
  • protectedbooleanA branch rule protects this branch.
  • push_refusalobjectoptionalWhy the caller may not push here, in a sentence to show them. Absent when they may.
  • repository_iduuid
  • 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.
DELETE/repositories/{repo_id}/branches/{branch_name}branch:delete

Delete a branch

delete_branchDELETE /repositories/{repo_id}/branches/{branch_name}Open in the API reference

Token scope

branch:delete

Send

Path
  • repo_iduuidRepository ID
  • branch_namestringBranch name

Refuses

  • 400Cannot delete the default branch
  • 401Unauthenticated — no credential, or an invalid one
  • 403The caller may not delete branches here, or a branch rule protects this branch
  • 404Branch not found
  • 409The branch is the target of an open merge request

Receive

No body.

Troubleshooting

400 BAD_REQUESTon any call, mentioning repo_id
Cause
The repository id in the URL is not a well-formed id — usually a path like my-group/my-repo pasted where an id belongs
What to do
Use the repository's id, or call the by-path endpoint that takes a path
400 BAD_REQUESTon create, mentioning the name
Cause
The name is not a valid git ref — a space, a .., a leading or trailing /, or a control character
What to do
Rename it. Letters, digits, -, _, . and / between segments are all safe
400 BAD_REQUESTon delete, mentioning the default branch
Cause
You are deleting the branch the repository defaults to, which is main on every repository
What to do
Nothing deletes it, and no setting moves the default elsewhere. If main holds the wrong history, push the history you want onto it and delete the other branch instead
409 CONFLICTon create
Cause
A branch with that name already exists
What to do
Pick another name, or delete the existing branch first if you meant to replace it. The existing branch is left exactly where it was
403 FORBIDDENon create
Cause
You have read access but not Developer, or a branch rule protects the name you chose (BRANCH_PROTECTED)
What to do
Ask an Owner or Maintainer of the repository to raise your access level, or pick a name the rule does not cover
403 FORBIDDENon delete, where create works
Cause
A branch rule protects the branch you are deleting and sets a push threshold above your level. Creating worked because the branch you created matched no such rule
What to do
Check the repository's branch rules for a pattern matching this branch. Ask an Owner or Maintainer to raise your level, to add you to the rule's push allowlist, or to delete the branch for you
403 INSUFFICIENT_SCOPE
Cause
Your token is valid but was minted without the scope this call needs
What to do
Mint a new token that carries branch:create or branch:delete. Scopes are chosen at mint time and cannot be added to a token afterwards
404 NOT_FOUNDon a repository you are sure exists
Cause
Either the repository is private and you are not a member, or the branch name is wrong
What to do
A private repository answers 404 rather than 403 to anyone who is not a member, so that its existence stays private. Check you are a member, then check the spelling
409 CONFLICTon delete
Cause
An open merge request is merging into this branch
What to do
Close the merge request, or retarget it at another branch, then delete
The branch is there in git but not in the list
Cause
The branch was pushed to a different repository, or the push was rejected by a push rule
What to do
Check the push output — a rejected push leaves nothing behind
  • Merge requestshow work on a branch gets reviewed and merged
  • Branch rulesprotecting a branch so it cannot be force-pushed or deleted
  • Push rulesconstraining what may be pushed to a branch in the first place