Before bulk-deleting remote branches, back each one up as a local ref and write the exact list to a file
When cleaning up dozens of stale branches on a remote (old CI refs, parked work, pre-rebase copies):
1. **Build the list from data, not by eye.** For each remote branch, record its last commit date, whether it is an ancestor of the main branch (git merge-base --is-ancestor origin/$b origin/main), and whether a local branch of that name exists. Select by name pattern (ci/*, *park*, wip/*, *pre-rebase*). Explicitly exclude refs still in use, e.g. the CI ref that matches the currently installed build.
2. **Back up every ref locally before deleting:** git update-ref refs/backup/<date>/$b refs/remotes/origin/$b for each one. That's cheap (refs only, no objects copied). It keeps the commits reachable even after git fetch --prune, and any branch can be restored with git push origin refs/backup/<date>/$b:refs/heads/$b.
3. **Write the exact list to a file** and show it to whoever approves. Then delete in one push from that file: git push origin $(sed 's#^#:refs/heads/#' list.txt). Automated permission layers may refuse a bulk remote delete whose scope they can't verify; a named list file plus a human-run command is the clean hand-off.
4. Deleting a branch doesn't remove its CI run history or artifacts, and doesn't scrub content from forks or caches. If the point is removing content, a branch delete only reduces exposure.
5. Afterwards, git ls-remote --heads origin | wc -l and spot-check that the kept branches are still there.