144

I have a team member who inadvertently pushed over 150 of his local branches to our central repo. Thankfully, they all have the same prefix. Using that prefix, is there a git command or cool little shell script I can use that will delete all of those at once?

Jake A. Smith
  • 2,157
  • 3
  • 16
  • 24

18 Answers18

175

Use the following command to remove all branches with PREFIX 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}'
neevek
  • 11,340
  • 8
  • 53
  • 71
  • 2
    I like this because it's a one liner and I can do a dry run first. Unfortunately, it errors out with this message: `$ git branch -r | awk -F/ '/\/APR/{print $2}' | xargs -I {} git push origin :{} error: unable to push to unqualified destination: APR-04-DPH The destination refspec neither matches an existing ref on the remote nor begins with refs/, and we are unable to guess a prefix based on the source ref. error: failed to push some refs to 'GIT_URL'` – Jake A. Smith May 11 '12 at 16:49
  • With `git branch -r | awk -F/ '/\/APR/{print $2}'`, could you see all the APR prefixed branch names listed? – neevek May 11 '12 at 17:04
  • 1
    OK, it is because the `APR-04-DPH` branch was already deleted. Take a look at these answered questions: [this](http://stackoverflow.com/questions/3184555/cleaning-up-old-remote-git-branches) and [this](http://stackoverflow.com/questions/6783917/why-cant-i-delete-a-remote-git-branch-with-git-push-origin-branchname) and also [this](http://stackoverflow.com/questions/2895906/cannot-delete-a-remote-branch-created-unintentionally). Answers to those questions address the same problem, you may want to test the solutions yourself. – neevek May 11 '12 at 17:11
  • Oh, you're right. Thanks for the research and your awesome help! – Jake A. Smith May 11 '12 at 17:14
  • 34
    if you have / in your branch names (if you're using git-flow or something), then print {$2"/"$3} instead – ajma Mar 09 '15 at 22:01
  • I don't know why it don't works for me. I found it works with `grep`. `git branch -r | grep -Eo 'PREFIX/.*' | xargs -I {} git push origin :{}` `branch -r` shows `origin/prefix/branchname`. So it will take `prefix/branchname`. – Kirby Jun 03 '15 at 11:49
  • 5
    I am using msysgit in Windows, and the following command worked for me (in conjunction with @ajma's comment for branch names containing forward slashes: `git branch -r | awk -F/ '/\/PREFIX/{print $2"/"$3}' | xargs -I % git push origin --delete %` – rikoe Oct 09 '15 at 10:54
  • @Artem Sure, you just need to use `git tag` to list the tags, the command line `git push origin :` applies to tags too. – neevek Dec 24 '15 at 05:37
  • I can do the dry run and see the expected branches but when I try to run the full command I get C:\Program Files (x86)\Gow\bin\xargs.exe: xml: No such file or directory any idea what might be the case? I've definitely used xargs in other scenario :( – Crhistian Ramirez Feb 21 '19 at 23:48
  • `C:\Program Files (x86)\Gow\bin\xargs.exe: xml`, Can you see that `xml`, I think it is complaining about that, not `xargs`, you must check that out, it may be related to the error you got. @CrhistianRamirez – neevek Feb 22 '19 at 00:33
  • This solution works regardless of how many folders you have: `git branch -r | grep PREFIX | sed 's/ origin\///'` – arlyon Jan 22 '21 at 08:54
  • I don't understand why this is so upvoted. It doesn't work for branches with multiple `/` and even with `{$2"/"$3}` it seems to find branches like /x/PREFIX/. Maybe it's me. – tymtam Feb 16 '22 at 01:36
110

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

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

Important: Only works on Git v1.7.0 and above.

jfeston
  • 1,392
  • 1
  • 8
  • 11
44

Thanks to Neevek for great and elegant solution!

But i have some troubles with slashes in branch names (i'm using Git Flow), because of awk field separator / (-F option)

So my solution is based on Neevek's, but correctly parses branch names with /. In this case i presume that your remote called origin. Command for deleting remote branches with names staring with PATTERN:

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

And don't forget to check what you are going to delete:

git branch -r | awk -Forigin/ '/\/PATTERN/ {print $2}'

USEFUL TIP: If your branch names (without origin/ prefix) stored in a text file (one branch name per line), just run:

cat your_file.txt | xargs -I {} git push origin :{}
Dmytro
  • 5,227
  • 2
  • 50
  • 50
  • 2
    Use `xargs -a file -L` instead of `cat file | xargs`. Even simpler `xargs -a file git push --delete origin`. – musiKk Sep 10 '15 at 06:16
  • When running with many remote branches that match the regex, this can take a while, since a single branch is deleted every time. In order to speed it up it's possible to run in parallel using the following command (the argument to -P chooses how many will run in parallel): `git branch -r | awk -Forigin/ '/\/PATTERN/ {print $2}' | xargs -n 1 -P 8 -I {} git push origin :{}` – DorHugi Jan 17 '21 at 09:57
33

This may be a duplicate answer but below tested and worked for me perfectly.

  1. Delete local branch forcefully

git branch -D branch-name

  1. Delete Remote branch

git push origin --delete branch-name

  1. Delete more than 1 local branch

git branch -D branch-name1 branch-name2

  1. Delete more than 1 remote branch

git push origin --delete branch-name1 branch-name2

  1. Delete local branch with prefix. For example, feature/*

git branch -D $(git branch --list 'feature/*')

git branch -D backticks $(git branch --list 'feature/*' backticks)

  1. List remote branch with prefix.

git branch -r | grep -Eo 'feature/.*'

  1. Delete remote branch with prefix

git branch -r | grep -Eo 'feature/.*' | xargs -I {} git push origin :{}

Stabledog
  • 2,866
  • 1
  • 28
  • 38
Naren
  • 1,244
  • 14
  • 18
  • 2
    i think you meant to escape the backticks in step 5 –  Feb 22 '19 at 22:28
  • How to add backticks? – Naren Jul 17 '19 at 13:15
  • 1
    @Naren: the problem is that the markdown formatting turns your backticks into a styling command. I replaced them with a different command substitution method (e.g. "$(command)" is equivalent to \`command\` but doesn't get translated by markdown into something weird.) The other thing you could do is escape the backticks with '\' – Stabledog Jul 18 '19 at 13:21
16

The same with grep: git branch -r | grep -Eo 'PREFIX/.*' | xargs -i git push origin :{}.

branch -r shows origin/prefix/branchname. So it will take prefix/branchname.

Kirby
  • 2,401
  • 1
  • 27
  • 40
  • I think you meant `xargs -I {} git push origin :{}`, not `-i`. – jojo Jul 13 '19 at 04:06
  • 2
    @jojo, AFAIK, for `-i` it uses default replacement for `{}` but with `-I` you may declare your own one. ...just found in the manual: `-i ... the same as -I{}` – Kirby Jul 15 '19 at 12:27
10

Neevek's solution is elegant, but it can be better: the solution as proposed calls 'git push' once per branch, which means an additional network round-trip per branch to be deleted. Since you're using awk anyway, why not use it to prefix the ':' and then xargs can call 'git push' exactly once and delete all the branches at once:

Dry-run to list the branches that would be deleted:

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

Final solution to actually push the deletes:

git branch -r | awk -F/ '/\/PREFIX/{print ":" $2}' | xargs git push origin
lack
  • 103
  • 1
  • 5
  • 2
    It works perfectly in the situation that you can't use "-I" option for xargs when you have a lower version bash or use a windows version git bash. – zchholmes Jan 23 '15 at 16:12
  • I had a `xargs: replstr may not be empty` with Neevek's solution, maybe git version.. `git version 1.9.5` But this worked great for me. Thanks to you both – iamface Mar 23 '15 at 23:12
9

resource https://coderwall.com/p/eis0ba

    1 - List all your remote branches:

    $ git branch -r

    2 - Filter the branches by some regular expression. In this case I'm 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:
    # **Edit** - Removed extra colon, which is not needed
    $ git branch -r | awk -F/ '/\/feature-/{print $2}' | xargs -I {} git push origin {}
    4 - Grab a beer.

    5 - Remove any local reference to those branches:

    $ git remote prune origin
Ashish Sajwan
  • 696
  • 8
  • 16
7

Thanks to Steve and Neevek, I found a solution that worked pretty well for me I figured worth sharing:

Steve's solution worked for me with one minor adjustment. My remotes were named origin/feature/some-feature-name so I trimmed your awk:

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

It's now doing a nice little delete flow:

To github.com:project/project-name.git
- [deleted]         feature/search-min-chars
To github.com:project/project-name.git
- [deleted]         feature/search-placeholder
To github.com:project/project-name.git
- [deleted]         feature/server-error-message
To github.com:project/project-name.git
- [deleted]         feature/six-point-asterisk

Was wondering if anyone had any ideas for a more elegant solution, though, that might output something like this (my CLI scripting is pretty poor, so it'd take me awhile to figure this out):

git push origin :feature/search-min-chars :feature/search-placeholder :feature/server-error-message :feature/six-point-asterisk

This would result in a nice single output with one network request:

To github.com:project/project-name.git
- [deleted]         feature/search-min-chars
- [deleted]         feature/search-placeholder
- [deleted]         feature/server-error-message
- [deleted]         feature/six-point-asterisk
andrewmart.in
  • 1,293
  • 13
  • 22
5

Thanks to Neevek. This worked well after reconfiguring it for my purpose:

git branch -r | awk -Forigin/ '/\/PATTERN/ {print $2 "/" $3}' | xargs -I {} git push origin :{}

I also needed take the folder structure into account. My feature-branches are in a folder structure like origin/feature/PREFIX-FEATURENUMBER. So i had to build up my pattern from $2=folder + $3= branchname.

Steve Bennett
  • 98,925
  • 29
  • 148
  • 200
user3416278
  • 61
  • 1
  • 3
5

Everyone is using awk, not sure why. I feel like that's more complex. Here is what I use to delete all remote branches on my fork remote:

$ git branch -r --list 'fork/*' | sed 's/fork\///' | xargs git push --delete fork

Throw in a grep between the xargs and sed if you need to filter the list down to only a subset of remote branches.

void.pointer
  • 23,191
  • 28
  • 120
  • 213
  • 1
    Thanks a lot. This one actually worked for me amongst all the solutions.. grep was returning the full branch with remote name as well like `origin/blaprefix_anotherbla`. But using `sed` handled it well. Another advantage of this approach, is that I use bitbucket and I dont need to enter authentication password for every branch deletion manually. This one does delete all the branches in a single batch. – Madhur Bhaiya Oct 17 '19 at 13:43
  • To delete all greenkeeper branches `git branch -r | egrep 'origin/greenkeeper' | sed 's/origin\///' | xargs -I {} git push origin --delete {}` – abhisekp Jul 19 '20 at 05:29
4

I realize this is for git command, but if you looking for an alternate solution to do the similar or same result:

You can do it from here (Git Remove Remote Branches):

Then select the branches you want:

Make sure you have the permissions to remove the remote branches.

Omar Einea
  • 2,420
  • 6
  • 22
  • 35
1

I was not able to use awk because we are using a slash structure for our branches' name.

git branch -r | grep "origin/users/YOURNAME" | sed -r 's/^.{9}//'| xargs -i  sh -c 'git push origin --delete {}'

This get all remote branch, get only the one for a single user, remote the "origin/" string and execute a delete on each of them.

Patrick Desjardins
  • 131,236
  • 84
  • 290
  • 340
1

Github also has a nice UI and mechanism for quickly deleting branches, that's if you'd rather use a UI

Alex
  • 71
  • 6
  • 1
    Yes, it's documented [here](https://help.github.com/articles/viewing-branches-in-your-repository/), but you still must click once for each individual branch. The top-voted solution here is the best way to do many branches that you can write a regex to match. – thewoolleyman Oct 28 '16 at 23:04
1

Dry run:

git branch -r --list 'origin/your-branch-name/*' | sed "s/origin\///" | xargs -I {} echo {}

Delete remote branches:

git branch -r --list 'origin/your-branch-name/*' | sed "s/origin\///" | xargs -I {} git push origin --delete {}

Delete only fully merged remote branches:

git branch -r --merged --list 'origin/your-branch-name/*' | sed "s/origin\///" | xargs -I {} git push origin --delete {}

Explanation:

sed "s/origin\///" will remove origin/ from the branch name. Without stripping that away I got: remote ref does not exist

Tobias Ernst
  • 3,488
  • 1
  • 28
  • 26
1

Previous answers helped me to remove all release branches from 2018. I ran this on my windows 10 command prompt. I have installed clink, so Linux like commands works for me.

Dry Run:

git branch -a | grep -o "release-.*2018" | xargs -I {} echo {}

If dry run shows branches that are not in remote/origin. Run below git prune command to fix and check again.

git remote prune origin

Delete once you are happy with the result above:

git branch -a | grep -o "release-.*2018" | xargs -I {} git push origin --delete {}

If you see: error: unable to delete 'release-...2018': remote ref does not exist. Then run the previous prune command and try again.

Damodar Bashyal
  • 931
  • 3
  • 16
  • 31
0

I tried to delete all origin/release/r1-1* remote branches, hence following command line worked nicely.

git branch -r | awk -Forigin/ '/\/*r1-1/ {print $2}' |  xargs -I {} git push origin :{}
Atish Narlawar
  • 590
  • 6
  • 14
0

Good solution in case of multiple remotes where we can find few PREFIX combinations. If you have many (let's say hundreds) branches that were created automatically for example such pattern: build/XXXX. In addition, there is upstream remote and forked origin so that branch -r returns origin/build/XXXX and upstream/build/XXXX as well.

You can use solution with command cut -f2- -d/ More: https://unix.stackexchange.com/a/354984

Dry run where one can combine safe regex patterns like: 33[1-3][0-9] or [0-9]{4}:

git branch -r | grep -Eo "upstream/build/33[0-9][0-9]" | cut -f2- -d/ | xargs -I {} echo {}

The same with real delete from the upstream:

git branch -r | grep -Eo "upstream/build/33[0-9][0-9]" | cut -f2- -d/ | xargs -I {} git push upstream --delete {}
dubwise
  • 21
  • 3
0

I use this to remove unwanted branches in the remote from time to time:

git branch -r --list origin/some/prefix/* | sed 's/origin\///' | xargs git push origin --delete

where brnaches starting with some/prefix are the unwanted ones.

This:

  • handles branches with (multiple) / in their names and
  • updates the list of remote branches (so git remote update origin --prune is not needed after running this)

Example:

git branch -r --list origin/bug/* | sed 's/origin\///' | xargs git push origin --delete

Deletes all branches starting with 'bug/'

enter image description here

tymtam
  • 24,269
  • 5
  • 71
  • 101