4

I have a Git remote that has 1000 branches, and I want to delete all the branches whose name does not start with foo_. Is there an easy way to do that?

jub0bs
  • 60,866
  • 25
  • 183
  • 186
Ram Rachum
  • 84,019
  • 84
  • 236
  • 374

3 Answers3

4

Short answer

If your remote is called "origin", run

git for-each-ref --format='%(refname:strip=3)' refs/remotes/origin/* | \
  grep -v '^foo_\|^HEAD$' | \
  xargs git push --delete origin

More details

Prefer git for-each-ref over git branch

The other answers suggest piping the output of git branch to grep or awk. However, such an approach is brittle: git branch is a Porcelain (i.e. high-level) command, whose output may change in a future Git release. A better alternative is to use git for-each-ref, a powerful Plumbing (i.e. low-level) command.

Explanation of the command

(Note: the following assumes that your remote is called "origin".)

Use git for-each-ref to list all the remote branches on origin in an adequate format:

git for-each-ref --format='%(refname:strip=3)' refs/remotes/origin/*

Pipe the output to

grep -v '^foo_\|HEAD$'

to discard HEAD and all the branches whose name starts with "foo_". Finally, pipe the output to

xargs git push --delete origin

to delete all the relevant remote branches from origin in one fell swoop.

Caveat: Of course, the command above won't be able to delete current branch of the remote if the latter doesn't start with "foo_".

jub0bs
  • 60,866
  • 25
  • 183
  • 186
  • 1
    Almost correct, except I said delete all the branches that *don't* start with foo. But I appreciate the use of `for-each-ref`, that looks superior. – Ram Rachum May 19 '16 at 15:17
  • 1
    @RamRachum Oops! I should have read your answer more carefully. I'll amend the answer accordingly. – jub0bs May 19 '16 at 15:45
  • Thanks! Can you explain why the * you had in your previous answer wasn't automatically expanded by bash before being processed by the git command? (Just curious) – Ram Rachum May 22 '16 at 04:56
  • @RamRachum I'm not sure what you referring to. The `*` I had *was* being expanded by bash before being processed by Git... – jub0bs May 22 '16 at 06:36
  • How can the `*` be expanded by Bash, unless I'm inside the `.git` folder? Because there isn't a `refs` folder in the repo root. – Ram Rachum May 25 '16 at 04:09
  • If you take the effort to use a plumbing command to get a "safe" output, you should at least escape the `*` in case someone creates a `refs` folder – pqnet Mar 26 '18 at 09:32
  • For EL7 users, this won't work with the default git 1.8.3.1. `fatal: unknown refname: format strip=3`. After enabling git 2.18 from SCL, the error doesn't appear anymore, for me at least. – zypA13510 Aug 29 '19 at 02:36
2

Please use the following command in order to remove all branches with PREFIX on remote server.

git branch -r | awk -F/ '/\/PREFIX/{print $2}' | xargs -I {} git push origin :{}

You may want to do a dry-run first to see if it is the branches that you want to remove:

git branch -r | awk -F/ '/\/PREFIX/{print $2}'

If you like a simpler approach, for instance delete 3 or 4 branches:

git push origin --delete <branch1> <branch2> <branch3>

For your further information:

1 - List all your remote branches:

 $ git branch -r

2 - Filter the branches by some regular expression. In this case we are interested in deleting any branch with the 'feature-' prefix:

 $ git branch -r | awk -F/ '/\/feature-/{print $2}'

3 - Pipe the last command to git push to delete them:

$ git branch -r | awk -F/ '/\/feature-/{print $2}' | xargs -I {} git push origin :{}

4 - Remove any local reference to those branches:

$ git remote prune origin
Chhabilal
  • 1,076
  • 11
  • 22
  • This looks like it could take a long time with 1000 git pushes over the network. Wouldn't it be better to populate a variable with branch names first and do one push? – Jeff Puckett May 17 '16 at 12:24
  • That could be an improvement possibility. Btw, Did you try this way already? – Chhabilal May 17 '16 at 12:33
1

You should be able to list all remote branches not starting with foo_ using:

git branch -l -r|grep -v 'origin/foo_'

If that looks OK to delete you can use xargs to redirect the output to a git push origin --delete command:

git branch -l -r|grep -v 'origin/foo_'|xargs git push origin --delete
Oldskool
  • 34,211
  • 7
  • 53
  • 66
  • Doesn't your `xargs git` command need an extra `-r` flag to delete remote branches? – Wim Mostmans May 17 '16 at 12:22
  • Will this work without fetching from the remote first? – Jeff Puckett May 17 '16 at 12:22
  • @WimMostmans It would, I updated it to use `git push origin --delete` instead, as per the [official documentation](https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches#Deleting-Remote-Branches). – Oldskool May 17 '16 at 12:23