# Gitlab Protected Branch

> GitLab protected branch operations via API. ALWAYS use this skill when user wants to: (1) view branch protection rules, (2) protect/unprotect branches, (3) configure push/merge access levels, (4) set up code owner approval requirements.

- Skill: `grandcamel/gitlab-protected-branch` (Agent Skill)
- Install (CLI): `npx skillmds@latest add grandcamel/gitlab-protected-branch`
- Raw SKILL.md: https://api.skillmd.com/api/skills/grandcamel/gitlab-protected-branch/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- License: MIT
- Author: grandcamel (https://skillmd.com/u/grandcamel)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/grandcamel/gitlab-protected-branch

---


# Protected Branch Skill

Branch protection management for GitLab using `glab api` raw endpoint calls.

## Quick Reference

| Operation | Command Pattern | Risk |
|-----------|-----------------|:----:|
| List protected | `glab api projects/:id/protected_branches` | - |
| Get protection | `glab api projects/:id/protected_branches/:name` | - |
| Protect branch | `glab api projects/:id/protected_branches -X POST -f ...` | ⚠️ |
| Update protection | `glab api projects/:id/protected_branches/:name -X PATCH -f ...` | ⚠️ |
| Unprotect branch | `glab api projects/:id/protected_branches/:name -X DELETE` | ⚠️⚠️ |

**Risk Legend**: - Safe | ⚠️ Caution | ⚠️⚠️ Warning | ⚠️⚠️⚠️ Danger

## When to Use This Skill

**ALWAYS use when:**
- User mentions "protect branch", "branch protection", "protected branches"
- User wants to restrict who can push/merge to a branch
- User mentions "force push", "code owners", "merge access"
- User wants to configure main/release branch security

**NEVER use when:**
- User wants to create/delete branches (use git or gitlab-repo)
- User wants to manage merge request approvals (different API)
- User wants to configure CI/CD for branches (use gitlab-ci)

## API Prerequisites

**Required Token Scopes:** `api`

**Permissions:**
- View protected branches: Developer+
- Manage protected branches: Maintainer+

**Premium Features:**
- Code owner approval: GitLab Premium
- Multiple access levels: GitLab Premium

## Access Levels

| Level | Value | Description |
|-------|:-----:|-------------|
| No access | 0 | Nobody can perform action |
| Developer | 30 | Developers and above |
| Maintainer | 40 | Maintainers and above |
| Admin | 60 | Instance admins only |

## Available Commands

### List Protected Branches

```bash
# List all protected branches
glab api projects/123/protected_branches --method GET

# With pagination
glab api projects/123/protected_branches --paginate

# Using project path
glab api "projects/$(echo 'mygroup/myproject' | jq -Rr @uri)/protected_branches"
```

### Get Protection Details

```bash
# Get protection for specific branch
glab api projects/123/protected_branches/main --method GET

# Branch with special characters (URL-encode)
glab api "projects/123/protected_branches/$(echo 'release/1.0' | jq -Rr @uri)"

# Branch with wildcard pattern
glab api "projects/123/protected_branches/$(echo 'feature/*' | jq -Rr @uri)"
```

### Protect a Branch

```bash
# Basic protection (maintainers push, developers merge)
glab api projects/123/protected_branches --method POST \
  -f name="main" \
  -f push_access_level=40 \
  -f merge_access_level=30

# Strict protection (only maintainers)
glab api projects/123/protected_branches --method POST \
  -f name="main" \
  -f push_access_level=40 \
  -f merge_access_level=40 \
  -f allow_force_push=false

# With code owner approval (Premium)
glab api projects/123/protected_branches --method POST \
  -f name="main" \
  -f push_access_level=40 \
  -f merge_access_level=30 \
  -f code_owner_approval_required=true

# Protect wildcard pattern
glab api projects/123/protected_branches --method POST \
  -f name="release/*" \
  -f push_access_level=40 \
  -f merge_access_level=40

# Allow developers to push, anyone to merge
glab api projects/123/protected_branches --method POST \
  -f name="develop" \
  -f push_access_level=30 \
  -f merge_access_level=30 \
  -f allow_force_push=false

# No direct push (only through MR)
glab api projects/123/protected_branches --method POST \
  -f name="main" \
  -f push_access_level=0 \
  -f merge_access_level=30
```

### Update Protection

```bash
# Change merge access level
glab api projects/123/protected_branches/main --method PATCH \
  -f merge_access_level=40

# Enable code owner approval (Premium)
glab api projects/123/protected_branches/main --method PATCH \
  -f code_owner_approval_required=true

# Allow force push (not recommended for main)
glab api projects/123/protected_branches/feature%2F* --method PATCH \
  -f allow_force_push=true
```

### Unprotect Branch

**Warning:** This removes all protection from the branch!

```bash
# Unprotect branch
glab api projects/123/protected_branches/main --method DELETE

# Unprotect wildcard pattern (URL-encode)
glab api "projects/123/protected_branches/$(echo 'feature/*' | jq -Rr @uri)" --method DELETE
```

## Protection Options

| Option | Type | Description |
|--------|------|-------------|
| `name` | string | Branch name or wildcard pattern |
| `push_access_level` | integer | Who can push (0, 30, 40, 60) |
| `merge_access_level` | integer | Who can merge MRs (0, 30, 40, 60) |
| `unprotect_access_level` | integer | Who can unprotect (40, 60) |
| `allow_force_push` | boolean | Allow force push to branch |
| `code_owner_approval_required` | boolean | Require code owner approval (Premium) |

## Wildcard Patterns

| Pattern | Matches |
|---------|---------|
| `*` | All branches |
| `feature/*` | `feature/login`, `feature/signup`, etc. |
| `release/*` | `release/1.0`, `release/2.0`, etc. |
| `hotfix/*` | `hotfix/bug-123`, etc. |
| `*-stable` | `1.0-stable`, `2.0-stable`, etc. |

## Common Workflows

### Workflow 1: Standard Branch Protection

```bash
# Protect main branch
glab api projects/123/protected_branches --method POST \
  -f name="main" \
  -f push_access_level=40 \
  -f merge_access_level=30 \
  -f allow_force_push=false

# Protect develop branch
glab api projects/123/protected_branches --method POST \
  -f name="develop" \
  -f push_access_level=30 \
  -f merge_access_level=30 \
  -f allow_force_push=false

# Protect release branches
glab api projects/123/protected_branches --method POST \
  -f name="release/*" \
  -f push_access_level=40 \
  -f merge_access_level=40
```

### Workflow 2: Audit Current Protections

```bash
# List all protections with details
glab api projects/123/protected_branches --paginate | \
  jq -r '.[] | "Branch: \(.name)\n  Push: \(.push_access_levels[0].access_level_description // "none")\n  Merge: \(.merge_access_levels[0].access_level_description // "none")\n  Force Push: \(.allow_force_push)\n"'
```

### Workflow 3: Lock Down Production Branch

```bash
# Strict protection: only maintainers, no force push, require code owners
glab api projects/123/protected_branches --method POST \
  -f name="production" \
  -f push_access_level=40 \
  -f merge_access_level=40 \
  -f allow_force_push=false \
  -f code_owner_approval_required=true
```

### Workflow 4: Temporarily Allow Push to Protected Branch

```bash
# 1. Check current protection
glab api projects/123/protected_branches/main

# 2. Update to allow developer push
glab api projects/123/protected_branches/main --method PATCH \
  -f push_access_level=30

# 3. Do the work...

# 4. Restore protection
glab api projects/123/protected_branches/main --method PATCH \
  -f push_access_level=40
```

### Workflow 5: Set Up GitFlow Protection

```bash
project_id=123

# Main - production (strict)
glab api projects/$project_id/protected_branches --method POST \
  -f name="main" \
  -f push_access_level=0 \
  -f merge_access_level=40 \
  -f allow_force_push=false

# Develop - integration
glab api projects/$project_id/protected_branches --method POST \
  -f name="develop" \
  -f push_access_level=30 \
  -f merge_access_level=30

# Feature branches - allow developers
glab api projects/$project_id/protected_branches --method POST \
  -f name="feature/*" \
  -f push_access_level=30 \
  -f merge_access_level=30

# Release branches - maintainers only
glab api projects/$project_id/protected_branches --method POST \
  -f name="release/*" \
  -f push_access_level=40 \
  -f merge_access_level=40

# Hotfix branches - maintainers only
glab api projects/$project_id/protected_branches --method POST \
  -f name="hotfix/*" \
  -f push_access_level=40 \
  -f merge_access_level=40
```

## Troubleshooting

| Issue | Cause | Solution |
|-------|-------|----------|
| 403 Forbidden | Not maintainer | Need Maintainer+ role |
| 404 Not Found | Branch doesn't exist or not protected | Check branch name |
| 400 Bad Request | Invalid access level | Use 0, 30, 40, or 60 |
| Branch still protected | Pattern match | Check for wildcard patterns |
| Cannot push to protected | Access level too low | Update protection or get higher role |

## Best Practices

1. **Always protect main**: At minimum, protect your default branch
2. **Use wildcards wisely**: Protect `release/*` instead of individual releases
3. **Avoid force push on main**: Set `allow_force_push=false`
4. **Document protections**: Keep track of your branch protection strategy
5. **Review regularly**: Audit protections periodically

## Related Documentation

- [API Helpers](../shared/docs/API_HELPERS.md)
- [Safeguards](../shared/docs/SAFEGUARDS.md)
- [Quick Reference](../shared/docs/QUICK_REFERENCE.md)
- [GitLab Protected Branches API](https://docs.gitlab.com/ee/api/protected_branches.html)

