Can you delete multiple branches in one command with Git?
I'd like to clean up my local repository开发者_运维百科, which has a ton of old branches: for example 3.2
, 3.2.1
, 3.2.2
, etc.
I was hoping for a sneaky way to remove a lot of them at once. Since they mostly follow a dot release convention, I thought maybe there was a shortcut to say:
git branch -D 3.2.*
and kill all 3.2.x branches.
I tried that command and it, of course, didn't work.
Not with that syntax. But you can do it like this:
git branch -D 3.2 3.2.1 3.2.2
Basically, git branch will delete multiple branch for you with a single invocation. Unfortunately it doesn't do branch name completion. Although, in bash, you can do:
git branch -D `git branch | grep -E '^3\.2\..*'`
You can use git branch --list to list the eligible branches, and use git branch -D/-d to remove the eligible branches.
One liner example:
git branch -d `git branch --list '3.2.*'`
Well, in the worst case, you could use:
git branch | grep '3\.2' | xargs git branch -D
git branch | cut -c3- | egrep "^3.2" | xargs git branch -D
^ ^ ^ ^
| | | |--- create arguments
| | | from standard input
| | |
| | |---your regexp
| |
| |--- skip asterisk
|--- list all
local
branches
EDIT:
A safer version (suggested by Jakub Narębski and Jefromi), as git branch output is not meant to be used in scripting:
git for-each-ref --format="%(refname:short)" refs/heads/3.2\* | xargs git branch -D
... or the xargs-free:
git branch -D `git for-each-ref --format="%(refname:short)" refs/heads/3.2\*`
Recently, I was looking for solution of same problem, finally i found one answer and it is working very well:
- Open the terminal, or equivalent.
- Type in git branch | grep " pattern " for a preview of the branches that will be deleted.
- Type in git branch | grep " pattern " | xargs git branch -D
This solution is awesome and if you want full explanation of each command and how it is working, its given here.
Use
git for-each-ref --format='%(refname:short)' 'refs/heads/3.2.*' |
xargs git branch -D
To delete multiple branches based on a specified pattern do the following:
Open the terminal, or equivalent and type in following commands:
git branch | grep "<pattern>" (preview of the branches based on pattern)
git branch | grep "<pattern>" | xargs git branch -D (replace the <pattern> with a regular expression to match your branch names)
Remove all 3.2.x
branches, you need to type
git branch | grep "3.2" | xargs git branch -D
That's all!
You are good to go!
Maybe You will find this useful:
If You want to remove all branches that are not for example 'master', 'foo' and 'bar'
git branch -D `git branch | grep -vE 'master|foo|bar'`
grep -v 'something' is a matcher with inversion.
I put my initials and a dash (at-) as the first three characters of the branch name for this exact reason:
git branch -D `git branch --list 'at-*'`
Keep "develop" and delete all others in local
git branch | grep -v "develop" | xargs git branch -D
If you want to delete multiple branches for cleanup this will work
git branch -d branch1 branch2 branch3
also if you want to reflect the deletion action to remote you can use this to push them
git push origin --delete branch1 branch2 branch3
Here is a general solution:
git branch | grep "<pattern>" | xargs git branch -D
I would suggest running the following command line before executing the above for a preview of the branches that will be deleted.
git branch | grep "<pattern>"
In this case
git branch | grep "^3\.2\..*" | xargs git branch -D
If you're not limited to using the git command prompt, then you can always run git gui
and use the Branch->Delete menu item. Select all the branches you want to delete and let it rip.
You can use git gui
to delete multiple branches at once.
From Command Prompt/Bash -> git gui
-> Remote -> Delete branch ... -> select remote branches you want to remove -> Delete.
If you really need clean all of your branches, try
git branch -d $(git branch)
It will delete all your local merged branches except the one you're currently checking in.
It's a good way to make your local clean
Powershell Solution:
If you're running windows, you can use PowerShell to remove multiple branches at once...
git branch -D ((git branch | Select-String -Pattern '^\s*3\.2\..*') | foreach{$_.ToString().Trim()})
//this will remove all branches starting with 3.2.
git branch -D ((git branch | Select-String -Pattern 'feature-*') | foreach{$_.ToString().Trim()})
// this will delete all branches that contains the word "feature-" as a substring.
You can also fine tune how the pattern matching should work using Powershell's Select-String command. Take a look at powershell docs.
For pure souls who use PowerShell here the small script
git branch -d $(git branch --list '3.2.*' | %{$_.Trim() })
I made a small function that might be useful based off of the answer provided by @gawi (above).
removeBranchesWithPrefix() {
git for-each-ref --format="%(refname:short)" refs/heads/$1\* | xargs git branch -d
}
Add that to your .bash_profile
and restart your terminal. Then you can call from command-line like this:
removeBranchesWithPrefix somePrefix
Note
I have it currently setup for a soft delete, which means it won't delete the branches unless they've already been merged. If you like to live on the edge, change -d
to -D
and it will delete everything with the prefix regardless!
git branch -d branch1 branch2 branch3
already works, but will be faster with Git 2.31 (Q1 2021).
Before, when removing many branches and tags, the code used to do so one ref at a time.
There is another API it can use to delete multiple refs, and it makes quite a lot of performance difference when the refs are packed.
See commit 8198907 (20 Jan 2021) by Phil Hord (phord
).
(Merged by Junio C Hamano -- gitster
-- in commit f6ef8ba, 05 Feb 2021)
8198907795
:usedelete_refs
when deleting tags or branchesAcked-by: Elijah Newren
Signed-off-by: Phil Hord
'
git tag -d
'(man) accepts one or more tag refs to delete, but each deletion is done by callingdelete_ref
on eachargv
.
This is very slow when removing from packed refs.
Usedelete_refs
instead so all the removals can be done inside a single transaction with a single update.Do the same for '
git branch -d
'(man).Since
delete_refs
performs all the packed-refs delete operations inside a single transaction, if any of the deletes fail then all them will be skipped.
In practice, none of them should fail since we verify the hash of each one before callingdelete_refs
, but some network error or odd permissions problem could have different results after this change.Also, since the file-backed deletions are not performed in the same transaction, those could succeed even when the packed-refs transaction fails.
After deleting branches, remove the branch config only if the branch ref was removed and was not subsequently added back in.
A manual test deleting 24,000 tags took about 30 minutes using
delete_ref
.
It takes about 5 seconds usingdelete_refs
.
TL;DR
git branch -D $(git branch | grep '3\.2\..*')
Explanation
git branch
lists all the branches on your local system.grep '3\.2\..*'
uses pattern matching to find all files in the current working directory starting with3.2.
. Using\
to escape.
as it's a special character for grep.git branch | grep '3\.2\..*'
will pass all the github branch names to the grep command which will then look for branch names starting with the string within the list supplied.$(git branch | grep '3\.2\..*')
Anything enclosed within$()
will run it as a separate shell command whose result can then be passed on to a separate command. In our case, we would want the list of files found to be deleted.git branch -D $(git branch | grep '3\.2\..*')
This just does what is explained above in Point 4.
You might like this little item... It pulls the list and asks for confirmation of each item before finally deleting all selections...
git branch -d `git for-each-ref --format="%(refname:short)" refs/heads/\* | while read -r line; do read -p "remove branch: $line (y/N)?" answer </dev/tty; case "$answer" in y|Y) echo "$line";; esac; done`
Use -D to force deletions (like usual).
For readability, here is that broken up line by line...
git branch -d `git for-each-ref --format="%(refname:short)" refs/heads/\* |
while read -r line; do
read -p "remove branch: $line (y/N)?" answer </dev/tty;
case "$answer" in y|Y) echo "$line";;
esac;
done`
here is the xargs approach...
git for-each-ref --format="%(refname:short)" refs/heads/\* |
while read -r line; do
read -p "remove branch: $line (y/N)?" answer </dev/tty;
case "$answer" in
y|Y) echo "$line";;
esac;
done | xargs git branch -D
finally, I like to have this in my .bashrc
alias gitselect='git for-each-ref --format="%(refname:short)" refs/heads/\* | while read -r line; do read -p "select branch: $line (y/N)?" answer </dev/tty; case "$answer" in y|Y) echo "$line";; esac; done'
That way I can just say
gitSelect | xargs git branch -D.
it works correctly for me:
git branch | xargs git branch -d
git branch | xargs git branch -D
delete all local branches
If you have installed Git GUI, which is a default add-on for Windows, then it's the simplest. You can use ctrl to choose multiple branches and delete them with one click.
Use the following command to remove all branches (checked out branch will not be deleted).
git branch | cut -d '*' -f 1 | tr -d " \t\r" | xargs git branch -d
Edit: I am using a Mac Os
You can use this command: git branch -D $(printf "%s\n" $(git branch) | grep '3.2')
If you had all the branches to delete in a text file (branches-to-del.txt) (one branch per line), then you could do this to delete all such branches from the remote (origin):
xargs -a branches-to-del.txt git push --delete origin
My specific case was not addressed, so I'm making a new answer...
Scenario:
- Freshly cloned repo
- No local branches created
- Many remote branches (over 100 in my case)
- I want to delete all the feature branches,
feature/myfeature
, from the remote
This is the command that I got to work:
git branch -a | cut -c3- | grep 'origin\/feature' | sed 's/remotes\/origin\///' | xargs git push origin --delete
Thanks to @gwai for putting me on the right track.
I you're on windows, you can use powershell to do this:
git branch | grep 'feature/*' |% { git branch -D $_.trim() }
replace feature/*
with any pattern you like.
I just cleaned up a large set of obsolete local/remote branches today.
Below is how I did it:
1. list all branch names to a text file:
git branch -a >> BranchNames.txt
2. append the branches I want to delete to command "git branch -D -r":
git branch -D -r origin/dirA/branch01 origin/dirB/branch02 origin/dirC/branch03 (... append whatever branch names)
3. execute the cmd
And this one works so much faster and reliable than "git push origin --delete".
This may not be the most smart way as listed in other answers, but this one is pretty straight forward, and easy to use.
As in Git all the branches are nothing by references to the git repo, why don't you just delete the branches going to .git/ref
and then if anything is left out which is not interesting in the repository will automatically be garbage collected so you don't need to bother.
精彩评论