我遵循一个开发过程,即为每个新功能或故事卡创建一个新的本地分支。完成后,我合并到主分支,然后推。

随着时间的推移,由于懒惰或健忘,我最终会得到一个很大的本地分支列表,其中一些(如spike)可能还没有合并。

我知道如何列出我所有的本地分支,我知道如何删除一个分支,但我想知道是否有一个git命令,允许我删除我所有的本地分支?

下面是git分支——merged命令的输出。

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

所有尝试删除grep -v \*列出的分支(根据下面的答案)都会导致错误:

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

我用的是:

git 1.7.4.1  
ubuntu 10.04  
GNU bash, version 4.1.5(1)-release  
GNU grep 2.5.4  

当前回答

不建议解析git分支的输出,这对于Stack Overflow的读者来说不是一个很好的答案。

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. 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. git branch may do other things that are annoying to parse, like put an asterisk next to the currently checked out branch

git的维护者对围绕git分支输出编写脚本有这样的看法

为了找出当前的分支是什么,随意/粗心的用户可能有 围绕git分支编写脚本,这是错误的。我们积极劝阻 反对使用任何瓷器命令,包括git分支,在 脚本,因为命令的输出可能更改为 帮助人类消费用例。

建议手动编辑. Git目录下的文件(如. Git /refs/heads)的答案同样有问题(refs可能在. Git / packs -refs中,或者Git可能在未来改变它们的内部布局)。

Git提供for-each-ref命令来检索分支列表。

Git 2.7。X将引入——merged选项,这样您就可以执行如下操作来查找并删除合并到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和更老的版本,您将需要列出所有本地分支,然后分别测试它们,以查看它们是否已经合并(这将显著地慢一些,并且稍微复杂一些)。

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

其他回答

我建议一个更温和的答案。这里的许多答案都使用-D,这是强制删除的,无论更改是否已合并。这里有一行代码,它不影响那些没有合并变更的分支。

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

或者你也可以试试其他例子,只要把-D改成-D就行了。我知道OP问如何删除,但在大多数情况下,使用-d更安全。

删除所有本地git分支,但保留主

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

提醒一下,我会升级到git 1.7.10。你可能在这里得到的答案并不适用于你的版本。我的猜测是你必须在分支名称前加上refs/heads/。

注意,只有在复制了工作文件夹和.git目录后,才能继续执行以下操作。

我有时直接从。git/refs/heads中删除我不想要的分支。所有这些分支都是文本文件,包含它们所指向的提交的40个字符sha-1。如果你为其中任何一个设置了特定的跟踪,你的.git/配置中将会有多余的信息。您也可以手动删除这些条目。

我在github上关于这个问题的评论中找到了一个更好的方法:

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

编辑:添加无颜色选项和排除稳定分支(根据您的情况添加其他分支)

'git branch -d'子命令可以删除多个分支。所以,简化@sblom的答案,但增加了一个关键的xargs:

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

或者,进一步简化为:

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

重要的是,正如@AndrewC所指出的,不鼓励使用git分支来编写脚本。要避免使用,可以使用如下语句:

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

删除时要谨慎!

$ 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).