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?

3 Answers 3

5

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_".

Sign up to request clarification or add additional context in comments.

7 Comments

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.
@RamRachum Oops! I should have read your answer more carefully. I'll amend the answer accordingly.
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)
@RamRachum I'm not sure what you referring to. The * I had was being expanded by bash before being processed by Git...
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.
|
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 

2 Comments

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?
That could be an improvement possibility. Btw, Did you try this way already?
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 

3 Comments

Doesn't your xargs git command need an extra -r flag to delete remote branches?
Will this work without fetching from the remote first?
@WimMostmans It would, I updated it to use git push origin --delete instead, as per the official documentation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.