503

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

由于懒惰或健忘,随着时间的推移往往会发生的情况是,我最终得到了大量本地分支,其中一些(例如尖峰)可能尚未合并。

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

下面是git branch --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,版本 4.1.5(1)-release
GNU grep 2.5.4

4

30 回答 30

605

'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 branch不鼓励使用 for scripting。为了避免它使用类似的东西:

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).
于 2012-05-16T00:43:24.020 回答
184

我在 github 上对此问题的评论中找到了更好的方法:

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

编辑:添加了无颜色选项并排除了稳定分支(根据需要添加其他分支)

于 2013-09-02T10:55:13.687 回答
179

删除所有分支但保留“develop”和“master”等其他分支的更简单方法如下:

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

很有用 !

于 2014-10-01T23:20:19.773 回答
155

git branch不建议解析 的输出,对于 Stack Overflow 上的未来读者来说,这也不是一个好的答案。

  1. git branch就是所谓的瓷器命令。Porcelain 命令不是为机器解析而设计的,输出可能会在不同版本的 Git 之间发生变化。
  2. 有一些用户配置选项会以git branch难以解析的方式更改输出(例如,着色)。如果用户已设置,那么您将在输出中获得控制代码,如果您尝试将其通过管道传递到另一个命令color.branch中,这将导致。error: branch 'foo' not found.您可以使用--no-color标志绕过它 to git branch,但谁知道其他用户配置可能会破坏事情。
  3. git branch可能会做其他令人讨厌的解析操作,例如在当前签出的分支旁边放一个星号

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

为了找出当前分支是什么,随意/粗心的用户可能已经围绕 git 分支编写了脚本,这是错误的。我们强烈反对在脚本中使用任何 Porcelain 命令,包括 git 分支,因为命令的输出可能会更改以帮助人类消费用例。

建议手动编辑目录中的.git文件(如 .git/refs/heads)的答案同样有问题(参考可能在 .git/packed-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
于 2014-10-02T00:01:31.843 回答
90

尝试以下 shell 命令:

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

解释:

  • git branch | grep -v "master"通过命令获取所有分支(master除外)
  • xargs使用命令选择每个分支
  • 删除分支xargs git branch -D
于 2019-09-27T17:52:34.363 回答
67

要删除除您当前已签出的分支之外的每个分支:

for b in `git branch --merged | grep -v \*`; do git branch -D $b; done

我建议更改git branch -D $becho $b前几次以确保它删除您想要的分支。

于 2012-05-15T23:50:03.457 回答
66

以下命令将删除除 master 分支之外的所有本地分支。

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

上面的命令

  1. 列出所有分支
  2. 从列表中忽略主分支并获取其余分支
  3. 删除分支
于 2018-08-24T14:08:20.540 回答
42

请注意,我会升级到 git 1.7.10。您可能会在这里得到不适用于您的版本的答案。我的猜测是您必须在分支名称前加上refs/heads/.

注意,仅当您制作了工作文件夹和 .git 目录的副本时,才继续执行以下操作。

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

于 2012-05-16T02:04:55.130 回答
40

删除linux 中的所有本地分支,除了你所在的分支

// hard delete

git branch -D $(git branch)
于 2019-04-05T07:54:30.540 回答
27

我发现只使用文本编辑器和 shell 更容易。

  1. 键入git checkout <TAB>外壳。将显示所有本地分支机构。
  2. 将它们复制到文本编辑器,删除您需要保留的那些。
  3. 用空格替换换行符。(在 SublimeText 中非常简单。)
  4. 打开外壳,输入git branch -D <PASTE THE BRANCHES NAMES HERE>.

而已。

于 2013-08-01T22:09:39.117 回答
18

如果要删除所有本地分支,请使用以下简单命令:

git branch -D `git branch`

注意:这将删除除当前签出分支之外的所有分支

于 2020-12-16T16:19:27.967 回答
16

在 Windows 命令行中,使用以下命令删除除当前签出分支之外的所有内容:

for /f "tokens=*" %f in ('git branch ^| find /v "*"') do git branch -D %f
于 2019-02-08T01:06:52.037 回答
13

我有类似的情况,最近发现以下命令很有用。

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep>/) printf "%s", $0 }'`

如果你想保留多个分支,那么

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep1>|<Branch_You_Want_to_Keep2>/) printf "%s", $0 }'`

希望这可以帮助某人。

于 2013-07-12T07:23:03.187 回答
11

这是适用于在 Windows 机器上运行的任何人的 Powershell 解决方案

git checkout master # by being on the master branch, you won't be able to delete it
foreach($branch in (git branch))
{
    git branch -D $branch.Trim()
}
于 2021-02-25T22:24:34.347 回答
9

如果你使用 NodeJS,我写了这个命令

npx git-clear-branch

该命令清除除 master 和 current 分支之外的所有本地分支。

于 2021-02-10T06:36:04.080 回答
7

如果您不需要通过 Git 本身,您也可以手动或以编程方式删除.git/refs/heads下的头。以下内容应在 Bash 下进行最少的调整:

shopt -s extglob
rm -rf .git/refs/heads/!(master)

这将删除除您的主分支之外的每个本地分支。由于您的上游分支存储在.git/refs/remotes下,它们将保持不变。

如果您不使用 Bash,或者想一次递归大量 Git 存储库,您可以使用 GNU find 执行类似的操作:

find . \
    -path remotes -path logs -prune -o \
    -wholename \*.git/refs/heads/\* \! -name master -print0 |
xargs -0 rm -rf

find 解决方案可能更便携,但修剪路径和文件名很棘手,并且可能更容易出错。

于 2012-05-16T02:34:55.997 回答
7

没有一个答案完全满足我的需求,所以我们开始吧:

git branch --merged | grep -E "(feature|bugfix|hotfix)/" | xargs git branch -D && git remote prune origin

这将删除所有合并并以feature/,bugfix/或开头的本地分支hotfix/。之后上游遥控器origin被修剪(您可能必须输入密码)。

适用于 Git 1.9.5。

于 2014-12-29T10:23:27.623 回答
7

尽管这不是命令行解决方案,但我很惊讶尚未建议使用Git GUI 。

我 99% 的时间都使用命令行,但在这种情况下,它要么很慢(因此是原始问题),要么在使用一些冗长但巧妙的 shell 操作时,您不知道要删除什么。

UI 解决了这个问题,因为您可以快速检查要删除的分支,并提醒您要保留的分支,而无需为每个分支键入命令。

从 UI 转到Branch --> DeleteCtrl+单击要删除的分支,以便突出显示它们。如果您想确保将它们合并到一个分支中(例如dev),请在“仅在合并到时删除”下将“本地分支”设置为dev。否则,将其设置为Always以忽略此检查。

GitUI:删除本地分支

于 2018-08-08T19:41:45.140 回答
6

基于此处的多个答案的组合-如果您想保留远程上存在的所有分支但删除其余分支,则以下 oneliner 可以解决问题:

git for-each-ref --format '%(refname:short)' refs/heads | grep -Ev `git ls-remote --quiet --heads origin | awk '{print substr($2, 12)}'| paste -sd "|" -` | xargs git branch -D
于 2019-03-27T06:34:35.777 回答
5

如果您想保留 master、develop 和所有远程分支。删除 Github 上不再存在的所有本地分支。

$ git fetch --prune

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

1] 它将删除远程存储库中不再使用的远程引用。

2] 这将获得所有分支的列表。从列表中删除包含 master、develop 或 origin(远程分支)的分支。删除列表中的所有分支。

警告 - 这也会删除您自己的本地分支。因此,当您合并分支并在合并、删除后进行清理时,请执行此操作。

于 2020-12-09T06:13:06.173 回答
3

git branch -d [branch name]用于本地删除

git branch -D [branch name]也用于本地删除,但强制删除

于 2020-09-05T14:41:59.077 回答
3
git branch -l |grep -v master | xargs git branch -D

但是在乎删除分支;如果它是一个小存储库,只需删除工作区并重新克隆它!

于 2021-09-08T05:18:25.520 回答
2

我建议一个更温和的答案。这里的许多答案都使用-D强制删除,无论更改是否已合并。这是一个单一的衬里,它使具有未合并更改的分支保持不变。

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

或者您可以尝试列出的其他示例,但只需-D-d. 我知道 OP 询问如何删除,但在大多数用例中,它使用起来更安全-d

于 2021-02-23T02:47:57.823 回答
2

对于 powershell,这将起作用:

git branch --format '%(refname:lstrip=2)' --merged `
    | Where-Object { $_ -ne 'master' } `
    | ForEach-Object { git branch -d $_ }
于 2019-08-01T17:29:21.010 回答
1

我的盒子上没有 grep 或其他 unix,但这在 VSCode 的终端上有效:

git branch -d $(git branch).trim()

我使用小写的 d 所以它不会删除未合并的分支。

当我这样做时我也在主人身上,所以* master不存在所以它没有尝试删除主人。

于 2020-04-08T19:05:18.350 回答
1

一次删除多个本地分支

# delete all local unmerged branches
git branch --no-merged | egrep -v "(^\*|master|dev)" | xargs git branch -D
# delete all local branches (merged and unmerged).
git branch | egrep -v "(^\*|master|dev)" | xargs git branch -D  

删除远程分支

# Deleting non-existent tracking branches
git remote prune <remote> --dry-run
# Deleting a single remote branch
git push <remote> --delete <branch>
# Deleting many remote branches at once
git branch -r --merged | egrep -v "(^\*|master|dev)" | sed 's/origin\///' | xargs -n 1 git push origin --delete

资源

于 2021-05-12T00:51:45.600 回答
0

以下脚本删除分支。使用它并自行承担修改等风险。

基于这个问题的其他答案,我最终为自己编写了一个快速的 bash 脚本。我称它为“gitbd”(git branch -D),但如果你使用它,你可以将它重命名为你想要的任何名称。

gitbd() {
if [ $# -le 1 ]
  then
    local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
    printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
    read -n 1 -r # Immediately continue after getting 1 keypress
    echo # Move to a new line
    if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
      then
        echo $branches_to_delete | xargs git branch -D
    fi
else
  echo "This command takes one arg (match pattern) or no args (match all)"
fi
}

它将提供删除与模式参数匹配的任何分支(如果传入),或者在不带参数调用时删除所有本地分支。它还会为您提供确认步骤,因为您知道,我们正在删除内容,这很好。

这有点愚蠢——如果没有与模式匹配的分支,它就不会意识到这一点。

示例输出运行:

$ gitbd test
Matching branches:

dummy+test1
dummy+test2
dummy+test3

Delete? [Y/n] 
于 2014-11-07T01:02:38.610 回答
0

我写了一个shell脚本来删除所有本地分支,除了develop

branches=$(git branch | tr -d " *")
output=""
for branch in $branches 
do
  if [[ $branch != "develop" ]]; then
    output="$output $branch"
  fi
done
git branch -d $output
于 2018-07-12T04:04:44.793 回答
0

以上答案工作正常。这是另一种方法,当我们在本地仓库中有很多分支并且我们必须删除许多分支,除了少数位于本地机器中的分支。

首先git branch将列出所有本地分支机构。

通过运行 unix 命令将分支名称列转换为文件中的单行
git branch > sample.txt
这会将其保存在sample.txt文件中。
awk 'BEGIN { ORS = " " } { print }' sample.txt
并在 shell 中运行 命令。这会将列转换为行并将分支名称列表复制到单行中。

然后运行
git branch -D branch_name(s)
这将删除本地存在的所有列出的分支

于 2018-09-28T06:57:33.820 回答
0

为此,您可以使用git-extras

$ git delete-merged-branches
Deleted feature/themes (was c029ab3).
Deleted feature/live_preview (was a81b002).
Deleted feature/dashboard (was 923befa).
于 2019-09-12T17:03:46.913 回答