I have many Git branches. How do I delete branches which have already been merged? Is there an easy way to delete them all instead of deleting them one by one?
You'll want to exclude the master
& develop
branches from those commands.
Local git clear:
git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d
Remote git clear:
git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin
Sync local registry of remote branches:
git fetch -p
To delete all branches on remote that are already merged:
git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin
In more recent versions of Git
git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin
UPDATE (by @oliver; since does not fit in comment, but enough answers already): if you are on branch ABC then ABC will appear in the results of git branch -r --merged
because the branch is not specified, so branch defaults to current branch, and a branch always qualifies as merged to itself (because there are no differences between a branch and itself!).
So either specify the branch:
git branch -r --merged master | grep -v master ...
OR first checkout master:
git checkout master | git branch -r --merged | grep -v ...
Alias version of Adam's updated answer:
[alias]
branch-cleanup = "!git branch --merged | egrep -v \"(^\\*|master|dev)\" | xargs git branch -d #"
Also, see this answer for handy tips on escaping complex aliases.
For those of you that are on Windows and prefer PowerShell scripts, here is one that deletes local merged branches:
function Remove-MergedBranches
{
git branch --merged |
ForEach-Object { $_.Trim() } |
Where-Object {$_ -NotMatch "^\*"} |
Where-Object {-not ( $_ -Like "*master" )} |
ForEach-Object { git branch -d $_ }
}
You can add the commit to the --merged option. This way you can make sure only to remove branches which are merged into i.e. the origin/master
Following command will remove merged branches from your origin.
git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete
You can test which branches will be removed replacing the git push origin --delete with echo
git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
The accepted solution is pretty good, but has the one issue that it also deletes local branches that were not yet merged into a remote.
If you look at the output of you will see something like
$ git branch --merged master -v
api_doc 3a05427 [gone] Start of describing the Java API
bla 52e080a Update wording.
branch-1.0 32f1a72 [maven-release-plugin] prepare release 1.0.1
initial_proposal 6e59fb0 [gone] Original proposal, converted to AsciiDoc.
issue_248 be2ba3c Skip unit-for-type checking. This needs more work. (#254)
master be2ba3c Skip unit-for-type checking. This needs more work. (#254)
Branches bla
and issue_248
are local branches that would be deleted silently.
But you can also see the word [gone]
, which indicate branches that had been pushed to a remote (which is now gone) and thus denote branches can be deleted.
The original answer can thus be changed to (split into multiline for shorter line length)
git branch --merged master -v | \
grep "\\[gone\\]" | \
sed -e 's/^..//' -e 's/\S* .*//' | \
xargs git branch -d
to protect the not yet merged branches. Also the grepping for master to protect it, is not needed, as this has a remote at origin and does not show up as gone.