Reputation: 21620
I want to delete all branches that get listed in the output of ...
$ git branch
... but keeping current branch, in one step. Is that possible? If so, how?
Upvotes: 176
Views: 109853
Reputation: 402
Working on macOS, remove the second grep if you also want to delete main
git branch | grep -v '*' | grep -v 'main' | xargs git branch -D
git branch
-> list branchesgrep -v '*'
-> remove current onegrep -v 'main'
-> remove mainxargs git branch -D
-> pipe the result to git branch -D
Upvotes: 1
Reputation: 2126
For Windows, in Powershell use:
git branch | %{ $_.Trim() } | ?{ $_ -ne 'master' } | %{ git branch -D $_ }
If you get an error with above, this works for me now:
git branch -D @(git branch | select-string -NotMatch "master" | Foreach {$_.Line.Trim()})
Upvotes: 24
Reputation: 3056
first (switch to the branch you want to keep > ex: master):
git checkout master
second (make sure you are on master):
git branch -D $(git branch)
And, If you're using PowerShell, use:
git branch -D $(git branch).Trim()
Upvotes: 179
Reputation: 8447
The current branch is marked with a *
e.g
git branch
branchA
branchB
* mybranch
otherthing
Just do
for b in $(git branch | grep -v \*); do git branch -D $b ; done
Do delete all branches NOT marked with a *
Upvotes: 4
Reputation: 13862
In Linux, the command you are looking for is:
git branch --list | grep -v "^* $(git branch --show-current)$" | xargs git branch -D
Here, git branch --show-current
is used to get the current branch instead of hard coding a branch name.
Upvotes: 2
Reputation: 71
You can just keep checked out branch you need to keep - checkout master in the current git worktree then use:
git branch | xargs git branch -D
You'll see couple of errors about impossibility to remove the checked out branch and "*" branch (the symbol which is placed in the branches list before checked out branch). If you have multiple worktrees for the local git repository other branches which are checked out there will be also kept with the same error (and additional errors while removing "+" branch accordingly to the symbol shown in the branches list before branches which are checked out in other worktrees of the current repository.
Upvotes: 1
Reputation: 131
Assuming you seek to delete all except the master branch and the current feature branch(lets call it 'team/features/dev-branch-name'), I'd like to condense it down to say:
To view the branches:
git branch | grep -v -Fx "$(git branch --show-current)\|master"
I see that some answers suggest grep -v "develop" | grep -v "master"
, but this is an AND condition i.e "give me all branch names that dont have "develop" in them and of those, find those that dont have "master" in them". Personally, I was looking for an OR condition.
Note to avoid accidental deletion of dev branch: although this looks great (due to no hardcoding of branch names), beware that you may not be checked out on the correct branch while you run this alongside a delete command. If your current branch checked out is master, then the above will list all except master only, whereas your intent was to list all except master and dev branch.
Thus I think it is best to make this foolproof by actually writing out the name of the branch you want to keep like so:
git branch | grep -v -Fx 'team/features/dev-branch-name\|master'
This has the benefit that you do not need to be checked out on a specific branch for it to correctly list.
Once you have successfully seen the branches you are about to delete, delete them by issuing:
git branch | grep -v -Fx 'team/features/dev-branch-name\|master' | xargs git branch -D
The above only adheres to deleting local branches. To delete remote branches too (which you'd want to do in cases like editing/trimming a cloned over repo for example), use:
git branch -r | grep -v -Fx 'team/features/dev-branch-name\|master' | cut -d'/' -f 2- | xargs -L 1 git push origin --delete
Couple of things going on here: -r
is to list all remote branches(if you've already deleted all the necessary local branches, then only the remote ones remain and you need to query for those specifically). -Fx
gets all the exact matches and -v
is a NOT condition. As per the man page for cut, to cut -d'/' -f 2-
means to divvy up the result by '/' and then take field 2 until the end of the line (-f 2-). This is useful if you wish to pipe team/features/dev-branch-name
instead of origin/team/features/dev-branch-name
to xargs
.
If you don't cut -d'/' -f 2-
, then you'd be saying git push origin --delete origin/branch
instead of git push origin --delete branch
. The former doesn't work. The -L 1
tell xargs
to provide the left hand side input to the git push
command one line at a time.
Even with the above, if you have remote branches that contain single quotation ('
) marks, it wont succeed on those. For that, you could try:
git branch -r | grep -v "'" | cut -d'/' -f 2- | xargs -L 1 git push origin --delete
I did have to delete these funky single quotation riddled branches manually due to a fatal: invalid spec
error.
Upvotes: 6
Reputation: 21
Easiest of all of the above:
Example:
git branch -d branch1 && git branch -d branch2 && git branch -d branch3 && git branch -d branch4 && git branch -d branch5 && ...
This works for me and I find it super easy to remove many branches together and I also get a message for each branch which gets deleted and error messages for those branches which fail to get deleted.
Upvotes: 1
Reputation: 1301
I use this because I get to be more selective in what I do not want to delete. This below command removes every branch except master, develop and the current branch.
BRANCHES=$(git branch | egrep -v "(master|develop|\*)" | xargs git branch -D)
echo $BRANCHES
So I put this in my ~/.zshrc
delete_branches() {
BRANCHES=$(git branch | egrep -v "(master|develop|\*)" | xargs git branch -D)
echo $BRANCHES
}
alias cleanup_branches=delete_branches
Upvotes: 6
Reputation: 777
To delete all branches except for the current branch in one step:
git branch | grep -v $(git rev-parse --abbrev-ref HEAD) | xargs git branch -D
Upvotes: 21
Reputation: 41
So I see a lot of hard coded branch names here... And I think my answer here is more accurate to the "current branch" part of the question whilst keeping it single line and readable to bash newbies like me. Just to place credit where it's due, the answer is rather obviously also based on @pankijs's answer.
git branch | grep -v $(git branch --show-current) | xargs git branch -d
and I have it aliased on one line in my .bash_aliases in debian aswell.
alias gitbclean='git branch | grep -v $(git branch --show-current) | xargs git branch -d'
(Though I thinks some bash features need to be enabled for the sub command to run on some command lines)
Upvotes: 1
Reputation: 767
Assuming git branch
shows the current branch prefixed with *
; Using Powershell the following one liner will delete all branches that don't start with *
.
git branch | ? { $_ -lt "*" } | % { git branch -D $_.Trim() }
?
= Where-Object
%
= Foreach-Object
Upvotes: 4
Reputation: 1465
Delete all merged branch locally:
git branch -D `git branch --merged | grep -v \* | xargs`
Delete all branches except a specific branch:
git branch | grep -v "branch name" | xargs git branch -D
Delete all local branches except develop and master
git branch | grep -v "develop" | grep -v "master" | xargs git branch -D
Upvotes: 8
Reputation: 1465
Delete all branches except a specific branch:
git branch | grep -v "branch name" | xargs git branch -D
Delete all local branches except develop and master
git branch | grep -v "develop" | grep -v "master" | xargs git branch -D
Upvotes: 30
Reputation: 6903
$ git branch | grep -v "master" | xargs git branch -D
will delete all branches except master (replace master with branch you want to keep, but then it will delete master)
Upvotes: 306
Reputation: 17997
Based on @pankijs answer, I made two git aliases:
[alias]
# Delete all local branches but master and the current one, only if they are fully merged with master.
br-delete-useless = "!f(){\
git branch | grep -v "master" | grep -v ^* | xargs git branch -d;\
}; f"
# Delete all local branches but master and the current one.
br-delete-useless-force = "!f(){\
git branch | grep -v "master" | grep -v ^* | xargs git branch -D;\
}; f"
To be added in ~/.gitconfig
And, as @torek pointed out:
Note that lowercase
-d
won't delete a "non fully merged" branch (see the documentation). Using-D
will delete such branches, even if this causes commits to become "lost"; use this with great care, as this deletes the branch reflogs as well, so that the usual "recover from accidental deletion" stuff does not work either.
Basically, never use the -force
version if you're not 300% sure you won't lose anything important. Because it's lost forever.
Upvotes: 87
Reputation: 1439
I once created this construct for my Windows environment. Maybe it'll help someone else. During execution, the master and current branch are not deleted. All other merged branches will be deleted regardless.
@echo off
cd PATH_TO_YOUR_REPO
REM -- Variable declerations
set "textFile=tempBranchInfo.txt"
set "branchToKeep=master"
set "branchToReplaceWith="
git branch --merged > %textFile%
REM -- remove "master" from list to keep the branch
for /f "delims=" %%i in ('type "%textFile%" ^& break ^> "%textFile%" ') do (
set "line=%%i"
setlocal enabledelayedexpansion
>>"%textFile%" echo(!line:%branchToKeep%=%branchToReplaceWith%!
endlocal
)
REM -- execute branch delete commands
for /f "delims=" %%a in (%textFile%) do (
git branch -D %%a
)
REM -- remove temp-file with branch information inside
DEL %textFile%
REM -- show local branches after the cleaning
echo Local branches:
git branch
pause
exit
Upvotes: 3
Reputation: 1897
IMHO, the safest way of removing local branches is:
git branch -av | grep "\[gone\]" | awk '{print $1}' | xargs git branch -d
Also, more info related to this topic you can find Delete all local git branches
Upvotes: 0
Reputation: 26196
To remove all merged branches(except current -v ‘*’
):
git branch --merged | grep -v '*' | xargs git branch -D
also I made such command for repo complete clean up:
alias git-clean="git branch | grep -v '*' | grep -v 'master' | xargs git branch -D && git reset --hard && git clean -d -x -f"
taken from here.
Upvotes: 14
Reputation: 488501
git branch -d
(or -D
) allows multiple branch names, but it's a bit tricky to automatically supply "all local branches excluding the one I'm on now" without writing at least a little bit of code.
The "best" (formally correct) method is to use git for-each-ref
to get the branch names:
git for-each-ref --format '%(refname:short)' refs/heads
but then it's even harder to figure out which branch you're on (git symbolic-ref HEAD
is the "formally correct" method for this, if you want to write a fancy script).
More conveniently, you can use git branch
, which prints your local branch names preceded by two spaces or (for the current branch) by an asterisk *
. So, run this through something to remove the *
version and you're left with space-separated branch names, which you can then pass to git branch -d
:
git branch -d $(git branch | grep -v '^*')
or:
git branch | grep -v '^*' | xargs git branch -d
Note that lowercase -d
won't delete a "non fully merged" branch (see the documentation). Using -D
will delete such branches, even if this causes commits to become "lost"; use this with great care, as this deletes the branch reflogs as well, so that the usual "recover from accidental deletion" stuff does not work either.
Upvotes: 13