Delete all local git branches

332,224

Solution 1

The 'git branch -d' subcommand can delete more than one branch. So, simplifying @sblom's answer but adding a critical xargs:

git branch -D `git branch --merged | grep -v \* | xargs`

or, further simplified to:

git branch --merged | grep -v \* | xargs git branch -D 

Importantly, as noted by @AndrewC, using git branch for scripting is discouraged. To avoid it use something like:

git for-each-ref --format '%(refname:short)' refs/heads | grep -v "master\|main" | xargs git branch -D

Caution warranted on deletes!

$ mkdir br
$ cd br; git init
Initialized empty Git repository in /Users/ebg/test/br/.git/
$ touch README; git add README; git commit -m 'First commit'
[master (root-commit) 1d738b5] First commit
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README
$ git branch Story-123-a
$ git branch Story-123-b
$ git branch Story-123-c
$ git branch --merged
  Story-123-a
  Story-123-b
  Story-123-c
* master
$ git branch --merged | grep -v \* | xargs
Story-123-a Story-123-b Story-123-c
$ git branch --merged | grep -v \* | xargs git branch -D
Deleted branch Story-123-a (was 1d738b5).
Deleted branch Story-123-b (was 1d738b5).
Deleted branch Story-123-c (was 1d738b5).

Solution 2

The simpler way to delete all branches but keeping others like "develop" and "master" is the following:

git branch | grep -v "develop" | grep -v "master" | xargs git branch -D

very useful !

Solution 3

I found a nicer way in a comment on this issue on github:

git branch --merged master --no-color | grep -v "master\|stable\|main" | xargs git branch -d

Edit: Added no-color option and excluding of stable branch (add other branches as needed in your case)

Solution 4

Parsing the output of git branch is not recommended, and not a good answer for future readers on Stack Overflow.

  1. git branch is what is known as a porcelain command. Porcelain commands are not designed to be machine parsed and the output may change between different versions of Git.
  2. There are user configuration options that change the output of git branch in a way that makes it difficult to parse (for instance, colorization). If a user has set color.branch then you will get control codes in the output, this will lead to error: branch 'foo' not found. if you attempt to pipe it into another command. You can bypass this with the --no-color flag to git branch, but who knows what other user configurations might break things.
  3. git branch may do other things that are annoying to parse, like put an asterisk next to the currently checked out branch

The maintainer of git has this to say about scripting around git branch output

To find out what the current branch is, casual/careless users may have scripted around git branch, which is wrong. We actively discourage against use of any Porcelain command, including git branch, in scripts, because the output from the command is subject to change to help human consumption use case.

Answers that suggest manually editing files in the .git directory (like .git/refs/heads) are similarly problematic (refs may be in .git/packed-refs instead, or Git may change their internal layout in the future).

Git provides the for-each-ref command to retrieve a list of branches.

Git 2.7.X will introduce the --merged option to so you could do something like the below to find and delete all branches merged into HEAD

for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
do
    git branch -d ${mergedBranch}
done

Git 2.6.X and older, you will need to list all local branches and then test them individually to see if they have been merged (which will be significantly slower and slightly more complicated).

for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
do
    git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
done

Solution 5

Try the following shell command:

git branch | grep -v "master" | xargs git branch -D

Explanation:

  • Get all branches (except for the master) via git branch | grep -v "master" command
  • Select every branch with xargs command
  • Delete branch with xargs git branch -D
Share:
332,224
Louth
Author by

Louth

Software engineer.

Updated on July 18, 2022

Comments

  • Louth
    Louth almost 2 years

    I follow a development process where I create a new local branch for every new feature or story card. When finished I merge the branch into master and then push.

    What tends to happen over time due to a combination of laziness or forgetfulness, is that I end up with a large list of local branches, some of which (such as spikes) may not have been merged.

    I know how to list all my local branches and I know how to remove a single branch but I was wondering if there was a git command that allows me to delete all my local branches?

    Below is the output of the git branch --merged command.

    user@machine:~/projects/application[master]$ git branch --merged
      STORY-123-Short-Description
      STORY-456-Another-Description
      STORY-789-Blah-Blah
    * master
    

    All attempts to delete branches listed with grep -v \* (as per the answers below) result in errors:

    error: branch 'STORY-123-Short-Description' not found.
    error: branch 'STORY-456-Another-Description' not found.
    error: branch 'STORY-789-Blah-Blah' not found.
    

    I'm using:
    git 1.7.4.1
    ubuntu 10.04
    GNU bash, version 4.1.5(1)-release
    GNU grep 2.5.4

  • Louth
    Louth almost 12 years
    with this command I get error:branch 'a_branch_name' not found. I can see what you're trying to do and I've been playing around with the command but for some reason git doesn't seem to like the branch names supplied...
  • Matti
    Matti almost 12 years
    hmmm. to help troubleshoot, it would be useful to see some example output from git branch --merged
  • Louth
    Louth almost 12 years
    my branch names are of the format STORY-123-Short-Description
  • Matti
    Matti almost 12 years
    and when you run git branch --merged, you get a list with one of those on each line?
  • Matti
    Matti almost 12 years
    does it literally say error:branch 'a_branch_name' not found.? Or does it complain about one of the branch names from your git branch output above?
  • Louth
    Louth almost 12 years
    it says error:branch 'STORY-123-Short-Description' not found. for each of the branches listed above.
  • Louth
    Louth almost 12 years
    This command still reports the same errors as mentioned in the comments for the answer below. error:branch 'STORY-123-Short-Description' not found. for each of the branches listed.
  • Louth
    Louth almost 12 years
    All the steps you've shown work for me, right up until git branch --merged | grep -v \* | xargs git branch -D and then I get the errors I've shown in the answer.
  • GoZoner
    GoZoner almost 12 years
    So, did using git 1.7.10 solve your problem or do you prefer working directly in the .git repository?
  • tassinari
    tassinari about 10 years
    Nice one but I needed backticks to get it to work git branch -D `git branch | awk '{ if ($0 !~ /master/) printf "%s", $0 }'` --Actually I think you did have them originally but they got lost in the SO formatting.
  • wheresrhys
    wheresrhys almost 10 years
    I've tried this but keep getting error: branch 'my-branch-name' not found. for every branch. Using git version 1.8.3.4 (Apple Git-47). Any idea why?
  • mBardos
    mBardos almost 10 years
    try 'git branch --merged master | grep -v master | xargs echo' to debug what exactly it is trying to delete? have no better ideas...
  • wheresrhys
    wheresrhys almost 10 years
    It's something to do with special characters added as part of colour coding. trying all sorts of sed variations to get rid of them
  • Andrew C
    Andrew C over 9 years
    You have resurrected an ages old thread and posted a virtually identical answer to an existing one, that is buggy and is missing the safety changes that it had. This is not a good answer.
  • Brent Bradburn
    Brent Bradburn over 9 years
    git branch --no-color 2>/dev/null?
  • Andrew C
    Andrew C over 9 years
    It's an improvement for sure. You will always have the problem of needing to filter out the *, and it does amusing things if somebody runs it from detached head. The main problem though is git branch is a porcelain command, and there is no guarantee that the output won't change in some future version of git.
  • Pam
    Pam over 8 years
    This answer is clear in piping output from git branch, modifying it, and passing to git branch -D. No need to be mean.
  • Павел Тявин
    Павел Тявин over 8 years
    So. git for-each-ref --format '%(refname:short)' refs/heads/ | grep -v master | xargs git branch -d
  • Alexander Bird
    Alexander Bird over 8 years
    This will not work if you have packed refs, or even if you cloned from a remote server sometimes (which will provide you packed files). If you refs are packed, then the refs will not be stored in .git/refs/heads, they will be stored in a file called "packed-refs". See git-scm.com/docs/git-pack-refs.
  • Jason
    Jason over 8 years
    Thank you @AndrewC - this is both answers the question bout the mysterious "branch not found" errors and provides a working solution using a more appropriate command! 👍
  • marcok
    marcok about 8 years
    If you get a error:branch 'STORY-123-Short-Description' not found. error, this is probably due to the git color settings. This worked for me (note the --no-color option): git branch --no-color --merged | grep -v \* | xargs git branch -D
  • GoZoner
    GoZoner about 8 years
    How are 'Porcelain' and 'non-Porcelain' GIT commands identified?
  • GoZoner
    GoZoner about 8 years
    Man pages for git on Mac OS... how quaint! :-)
  • mBardos
    mBardos almost 8 years
    @wheresrhys see the --no-color switch for git branch (edited my response too)
  • Volem
    Volem about 7 years
    Learned xargs usage together with this. Thanks
  • Igor Mironenko
    Igor Mironenko over 6 years
    Probably would be a useful enhancement to exclude 'dev' and 'master' by default?
  • Andrew C
    Andrew C over 6 years
    @PandaWood - git branch -d will refuse to delete the currently checked out branch (error: Cannot delete branch 'master' checked out). Any other branch is fair game if it is merged.
  • Dong Thang
    Dong Thang almost 6 years
    I don't think you can remove the branch which you are stand on.
  • krozaine
    krozaine over 5 years
    Instead of --merged there is another option --no-merged for other branches, if anyone is looking for it. You will need to use git branch -D ${noMergedBranch} instead
  • Jonas Lomholdt
    Jonas Lomholdt over 5 years
    I would use git branch | grep -v "master" | xargs git branch -d first so I don't delete unmerged branches, just to be safe. But nice answer!
  • Jonas Lomholdt
    Jonas Lomholdt over 5 years
    Here is a powershell version ,@(git branch | Select-String -Pattern "[^(*?)\s? master]") | ForEach-Object{$_.Line.Trim()} | %{git branch -D $_}
  • Moberg
    Moberg over 5 years
    It seems like a bad idea to remove the branch you have checked out at the moment
  • Melanie
    Melanie over 5 years
    @Dong There's a * beside that branch so you just remove it from the copied list!
  • Romain Valeri
    Romain Valeri about 5 years
    @Moberg Just checkout a commit beforehand, and your detached HEAD will float all right.
  • nelsontruran
    nelsontruran almost 5 years
    This one feels safer than going into .git and removing stuff.
  • Prad
    Prad almost 5 years
    This solution worked for me. Deleted all local branches.
  • KthProg
    KthProg almost 5 years
    @baklazan this would only work in Windows 10 command line if you have some tools installed. You probably have MINGW or some other such thing and you don't know it.
  • django
    django over 4 years
    This will not delete any branch contains word develop or master like 'develop_feature' or 'master_feature'.
  • RyanNerd
    RyanNerd over 4 years
    Although this may be a correct answer. One line of code isn't very useful without an explanation of what and how it solves the original question. Please provide details to your answer.
  • Brett Rowberry
    Brett Rowberry almost 4 years
    Confirmed: If not on master, this command WILL delete master.
  • its4zahoor
    its4zahoor almost 4 years
    How to delete all other branches except master and some other branch say branchA using this one line command? Currently I do git branch | grep -v "master" | grep -v "branchA" | xargs git branch -D
  • Julian
    Julian over 3 years
    I would also put a git checkout master in front: git checkout master; git branch | grep -v "master" | xargs git branch -D
  • JmLavoier
    JmLavoier over 3 years
    After a long time, I'm here to share another solution for Node.js developers. github.com/jmlavoier/clear-branches npx clear-branches.
  • Michael Berry
    Michael Berry over 3 years
    Not an issue in 2012, but these days probably makes sense to use grep -Ev 'main|master' instead, to capture both the common options.
  • SeleM
    SeleM over 3 years
    this wont delete a branch named "developX" (any develop* or master* branches wont be deleted as well)
  • perepm
    perepm about 3 years
    Has anyone managed to turn this into a git alias? That would be extremely convenient
  • perepm
    perepm about 3 years
    1. Substitute single quotes for double quotes like this: for mergedBranch in $(git for-each-ref --format "%(refname:short)" --merged HEAD refs/heads/) do git branch -d ${mergedBranch} done 2. git config --global alias.delete-merged-branches 'for mergedBranch in $(git for-each-ref --format "%(refname:short)" --merged HEAD refs/heads/) note: open the single quote but don't close it. This lets you enter more than one line of text
  • aloisdg
    aloisdg about 3 years
    I remove all my features with foreach($branch in (git branch)) { if ($branch.trim().startswith("feature")) {git branch -D $branch.trim()} }. Thank you :)
  • andreas.herz
    andreas.herz almost 3 years
    Did not work for me. Got the following error: fatal: branch name required
  • bvdb
    bvdb almost 3 years
    on windows 10, when I put this in a .bat or .cmd file, it says: f was unexpected at this time. Do, I need to change something about the %f parameters ?
  • kiewic
    kiewic almost 3 years
    From a .cmd file, you need to replace %f with %%f
  • arni
    arni almost 3 years
    Just for reference, this will delete all branches containing "chore": for /f "tokens=*" %f in ('git branch ^| find "chore"') do git branch -D %f
  • Brian Leishman
    Brian Leishman over 2 years
    If your branch has quotes in it, this doesn't work
  • LeGEC
    LeGEC over 2 years
    @ppicom : an alternative way to aliases is : create a script named git-foo, accessible from your path. git will now execute that script when you invoke git foo.
  • jthill
    jthill over 2 years
    git checkout @^0; git for-each-ref --merged --format='delete %(refname)' refs/heads | git update-ref --stdin; git will re-set-up any remote branches you check out.
  • melvio
    melvio over 2 years
    If you are reading this in 2021. It is likely that you'll encounter fatal: malformed object name master, fatal: branch name required. This is because a lot of github projects don't have a master branch anymore. They often use main instead. In this case, replace the git branch --merged master by git branch --merged main.
  • Robin Bastiaan
    Robin Bastiaan over 2 years
    How could you make this into an alias for easy use? I tried git config --global alias.dbr "the command..." but I got an error: unknown switch 'v'. This is because this is not a git thing.
  • Jefferson Lima
    Jefferson Lima over 2 years
    I believe it should be -D (capital D)
  • Ali Alizade
    Ali Alizade over 2 years
    This command very useful
  • mBardos
    mBardos over 2 years
    @JeffersonLima afaik -D deletes remote branches too. The question was about local branches.
  • Jefferson Lima
    Jefferson Lima over 2 years
    @mBardos you are right. In fact, the -D option issues a -d -f, i. e. according to the docs "allow deleting the branch irrespective of its merged status, or whether it even points to a valid commit"
  • shanti
    shanti about 2 years
    Why do I get errors like these? error: branch '<branch-name>' not found. These branches exist on local that's why it is trying to find them...
  • Rodrigo
    Rodrigo almost 2 years
    I completely disagree with Andrew C's comment, I am here in 2022 and the solution worked perfectly for me. Thanks geoom
  • Nick
    Nick almost 2 years
    add "--force" at the end if you really mean it.