feat(repo): add prune command to delete merged local branches
Description
Adds glab repo prune, which deletes local Git branches whose source branch has at least one merged merge request on GitLab and no still-open MRs from the same branch.
This replaces the workflow served by gitlab-org/gitlab's scripts/prune_merged_branches and — unlike git branch --merged — correctly identifies branches merged via squash and rebase strategies (which rewrite commit SHAs and look like distinct commits to Git).
Behavior
- Lists local branches via
git for-each-ref refs/heads/. - For each branch, fetches all pages of merge requests with that branch as the source.
- A branch is deletable only if it has ≥1 merged MR and zero open/locked MRs from the same source — the conservative safe choice when a branch name has been reused.
- The default branch, the currently checked-out branch, and protected branches (fetched from the GitLab API) are always excluded.
--excludeadds extra patterns. Wildcards follow GitLab's protected-branch semantics:*matches any character (including/),?matches exactly one.--mergedskips only the per-branch MR lookup and falls back togit branch --merged(fast-forward only). The default branch and protected branches are still fetched from GitLab in this mode.--dry-runpreviews;--yesskips the confirmation prompt. Non-interactive without--yesis a hard error.- Command is marked
mcpannotations.Destructive: "true".
Flags
| Flag | Description |
|---|---|
--dry-run |
Preview branches that would be deleted. |
-y, --yes |
Skip the confirmation prompt. |
-e, --exclude |
Branch name or glob pattern to exclude. Comma-separated or repeated. |
--merged |
Use git branch --merged instead of the GitLab API. |
Related issues
Closes #8142 (closed)
How has this been tested?
- Unit tests covering: happy path, dry-run, protected-branch exclusion (including GitLab wildcard patterns like
release*that must span/), user--excludepatterns, current-branch skipping, the merged+open-MR safety case, MR pagination (open MR on a later page must veto deletion), the--mergedgit-native path, non-interactive guard, protected-branches API failure, and the wildcard matcher itself. - Local smoke test via
glab repo prune --help. go vet,gofmt, package and adjacent tests all pass.
Reviewer notes
The original implementation has been substantively reworked in response to review:
- Per-branch MR lookup is now paginated (was missing open MRs on later pages).
- The wildcard matcher now uses GitLab semantics so
release*excludesrelease/1.0(the oldfilepath.Matchdid not span/). --include-currentwas removed —git branch -Drefuses the checked-out branch, so the flag could never do anything useful.- Production code now calls
client.Projects.GetProjectandclient.MergeRequests.ListProjectMergeRequestsdirectly so tests use thegitlabtestingmock client throughout, witht.Parallel()on every test.
Edited by Kai Armstrong