Skip to content

Instantly share code, notes, and snippets.

@schacon
Created April 26, 2011 19:19
Show Gist options
  • Save schacon/942899 to your computer and use it in GitHub Desktop.
Save schacon/942899 to your computer and use it in GitHub Desktop.
delete all remote branches that have already been merged into master
$ git branch -r --merged |
grep origin |
grep -v '>' |
grep -v master |
xargs -L1 |
awk '{split($0,a,"/"); print a[2]}' |
xargs git push origin --delete
@stevenkampen
Copy link

git branch -r --merged | 
grep origin | 
grep -v '>' | 
grep -v master | 
xargs -L1 | 
cut -d"/" -f2- | 
xargs git push origin --delete

@young40
Copy link

young40 commented Oct 15, 2014

greate

@guneysus
Copy link

I am using git-fiow and I dont wanna delete the origin/develop?

@rtpg
Copy link

rtpg commented Sep 29, 2015

@guneysus : replace grep -v master with grep -v develop

@arielelkin
Copy link

If you get a error: unable to delete 'origin/myBranch-1234': remote ref does not exist, run git fetch -p origin before.

I actually added that command to my version of the script (note that it's for branches from develop):

git fetch -p origin && git branch -r --merged | grep origin |grep -v '>' | grep -v develop | xargs -L1 | cut -d"/" -f2- | xargs git push origin --delete

@Emuentes
Copy link

Emuentes commented May 16, 2016

I tried this,
https://gist.github.com/Emuentes/80c96c3927911dae6e19

Works for me, I also use git-flow @guneysus

@zsoobhan
Copy link

zsoobhan commented Oct 11, 2016

@arielelkin I had the same issue. My solution was to run it in a for loop.

for branch in $(git branch -r --merged master | grep origin | grep -v develop | grep -v master | sed -E "s|^ *origin/||g")
do
    git push origin $branch --delete
done

https://gist.github.com/zsoobhan/53b598da50a5496f655a07bb9fb39151

@webysther
Copy link

For clean projects using /feature or /fix.

$ git fetch --prune;
$ git branch --remote --merged |
    grep origin |
    grep -v '>' |
    grep -v master |
    grep -v develop |
    xargs -L1 |
    cut -d"/" -f2- |
    xargs git push origin --delete;

@tkreuder
Copy link

tkreuder commented Apr 12, 2017

git fetch --prune; git branch -r --merged | grep origin | grep -v '>' | grep -v master | xargs -L1 | awk '{sub(/origin//,"");print}' | xargs git push origin --delete

In my case this would also delete the branches {development, release}, which is probably not what you want.

@starkcoffee
Copy link

starkcoffee commented May 10, 2017

awk is cool but a bit overkill. sed is cooler.

git branch -r --merged | grep origin | grep -v '>' | grep -v master | sed 's/origin\///' | xargs git push origin --delete

@kalkin
Copy link

kalkin commented Aug 31, 2017

sed is fine, but cut is more appropriate here. Also when using egrep it get shorter:

git branch -r --merged | grep origin | egrep -v '>|master' | cut -d/ -f2- | xargs git push origin --delete

@spezifanta
Copy link

I use sed so I am not limited to origin.
git fetch --all --prune && git branch --remote --merged | grep -v -P 'master|develop$' | sed -e 's/\// /g' | xargs -L1 -r git push -d; echo Done cleaning remote branches.

@hervenivon
Copy link

For the speedy users, do not forget the common develop branch

@voiski
Copy link

voiski commented Jan 31, 2018

Hi, thanks all for the tip to drop a huge list of merged branches but I believe that we can save time pushing all branches together to have one unique transaction:

git push origin --delete $(git branch -r --merged origin/master |  grep origin | egrep -v '>|master|develop' | cut -d/ -f2-)

@dimified
Copy link

dimified commented Feb 9, 2018

I like your solution @voiski. Can this somehow also be improved to avoid this message when no refs exist:

fatal: --delete doesn't make sense without any refs

@gustavomdsantos
Copy link

Best answer in my opinion @voiski 👏 👏 👏

@rcdailey
Copy link

rcdailey commented Aug 22, 2018

I created a script named git-merged on my PATH. Git recognizes this syntax and allows you to execute these scripts as if they are aliases. In this case, this script allows you to run git merged. The contents of the script are as follows:

#!/usr/bin/env bash
remote="${1:-origin}"
branch="$2"
git branch -r --list "$remote/*" --merged $branch \
    | sed "s/\s*$remote\///" \
    | egrep -v "^(HEAD|release|hotfix|master|develop)"

With this script, you can list merged branches on the remote (default behavior is to check remote origin for branches merged to HEAD):

$ git merged

You can fully specify the remote and target branch to check for merges:

$ git merged origin my-topic

Example above checks all remote tracking branches on remote origin that are merged to local branch my-topic. Using xargs, you can use this to effectively delete all merged branches on the remote:

$ git merged | xargs git push origin --delete

You can add the -n option to do a dry push to verify what will happen before you actually delete anything:

$ git merged | xargs git push origin --delete -n

The following branch patterns are ignored (supports git-flow branch naming):

  • release/1.2.3
  • hotfix/1.2.3
  • develop
  • master
  • origin/HEAD

The intention is to explicitly clean up stale, merged branches for feature development such as:

  • feature/my-thing
  • bugfix/crash-issue
  • my-topic-branch

@030
Copy link

030 commented Sep 19, 2018

Could you replace the current awk statement that resides in the gist file with the suggestion by @catsby, i.e. awk '{sub(/origin\//,"");print}'?

@christopher-hopper
Copy link

Here's a bash version, that doesn't rely on awk or sed or xargs.

for branch in $(git branch -r --merged master | grep origin | grep -v develop | grep -v master);
do
  git push origin --delete "${branch##*/}";
done

@ryan-collingham
Copy link

Here's a bash version, that doesn't rely on awk or sed or xargs.

for branch in $(git branch -r --merged master | grep origin | grep -v develop | grep -v master);
do
  git push origin --delete "${branch##*/}";
done

Clearest solution I've seen, it makes the intent much more explicit than a long chain of awk/sed/xarg calls.

Only thing I'd add is that it doesn't quite work for branches that have a '/' in the name - if branch="origin/foo/bar" then ${branch##*/} will be "bar" and not "foo/bar"! You can fix by using the non-greedy single # to match the substring:

for branch in $(git branch -r --merged master | grep origin | grep -v develop | grep -v master)
do
  git push origin --delete "${branch#*/}"
done

@ryanc414
Copy link

ryanc414 commented Jul 1, 2019

My solution to prune merged branches from local + multiple remotes, based on snippets above:

https://gist.github.com/ryanc414/f7686d2c97808b41ed8518a5840e2d78

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment