Detach a Supabase branch from its git branch without deleting it
A persistent Supabase branch linked to a git branch redeploys on every push to that git branch. Sometimes you want the deploys to stop but the branch - and its data - to stay: a staging environment you are freezing, or a branch whose automation you are handing to CI. Deleting and recreating the branch loses the data and the project ref. You do not have to. The git link is an editable field on the branch object, and clearing it stops the deploy loop. Everything below was measured on a GitHub-integrated project with a live persistent branch on 2026-08-21.
To follow along: a Supabase personal access token, the parent project ref,
and the branch ID (the UUID from GET /v1/projects/{ref}/branches, not the
branch name or project ref).
Step 1: Find the branch ID
Section titled “Step 1: Find the branch ID”REF=<parent-project-ref>curl -s "https://api.supabase.com/v1/projects/$REF/branches" \ -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \ | jq '.[] | {id, name, git_branch, persistent, status}'The git_branch field is the link. A branch created through the GitHub
integration has it set (e.g. "staging"); a branch created without a git
branch has it null.
Step 2: Clear the link
Section titled “Step 2: Clear the link”PATCH the branch with an empty string, not null:
BID=<branch-id>curl -s -X PATCH "https://api.supabase.com/v1/branches/$BID" \ -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"git_branch":""}'The CLI does the same thing through the same endpoint:
supabase branches update <branch-name> --git-branch "" --project-ref $REFBoth paths measured working on a fully deployed (FUNCTIONS_DEPLOYED)
persistent branch. The change persists: a follow-up GET shows
"git_branch": "".
Step 3: Verify the deploy loop is off
Section titled “Step 3: Verify the deploy loop is off”Push a commit to the git branch that used to drive the branch. Measured A/B on the same branch, same git branch, before and after clearing:
| Push with link set | Push with link cleared |
|---|---|
Supabase Preview check run goes in_progress | Check run completed with conclusion skipped |
Branch goes to CREATING_PROJECT (full redeploy) | Branch stays FUNCTIONS_DEPLOYED, untouched |
The check run still appears on the commit because the GitHub App is still installed on the repository - it just does nothing. If the skipped check itself is noise, the remaining lever is the integration’s repository settings, not the branch.
Reattach the link
Section titled “Reattach the link”Relinking is the same call with the branch name back:
curl -s -X PATCH "https://api.supabase.com/v1/branches/$BID" \ -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"git_branch":"staging"}'The name is validated against the connected repository - a branch that does not exist on the repo is rejected at create and update time. After relinking, the next push redeploys the branch again (measured).
Adjacent finding: deleting a persistent branch
Section titled “Adjacent finding: deleting a persistent branch”DELETE /v1/branches/{id} on a persistent branch
returns 400 {"message":"Cannot delete persistent branch."}. Set it
ephemeral first, then delete:
curl -s -X PATCH "https://api.supabase.com/v1/branches/$BID" \ -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"persistent":false}'curl -s -X DELETE "https://api.supabase.com/v1/branches/$BID" \ -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN"How it was checked
Section titled “How it was checked”| Claim | How it was checked |
|---|---|
{"git_branch":""} clears the link | PATCH + GET round-trip on a live persistent branch, twice |
null is a no-op | Same round-trip; GET showed the link unchanged |
| Cleared link stops deploys | Pushed a real commit before/after; check-run state and branch status compared |
| Relink restores deploys | Re-set the link, pushed again; branch redeployed |
CLI --git-branch "" works | supabase branches update + GET round-trip |
| Delete blocked on persistent branches | DELETE attempt, then persistent:false PATCH + DELETE success |
The official branching docs cover delete-and-recreate for rollbacks and re-seeding but do not document clearing the git link; the behavior above is measured, not documented.1
References
Section titled “References”-
Supabase, “Branching,” Supabase Docs. https://supabase.com/docs/guides/deployment/branching ↩