【问题标题】:Delete all local git branches删除所有本地 git 分支
【发布时间】:2012-05-23 12:44:36
【问题描述】:

我遵循一个开发流程,为每个新功能或故事卡创建一个新的本地分支。完成后,我将分支合并到 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.

我正在使用:
混帐 1.7.4.1
Ubuntu 10.04
GNU bash,版本 4.1.5(1)-发布
GNU grep 2.5.4

【问题讨论】:

  • 不是一个答案,而是我经常做的一件事,当我达到最高的懒惰并且本地克隆非常脏时,我只需 rm -rf /my_cool_repo 并重新克隆 repo。如果我没有一个活动分支,这是“清除所有本地分支”IMO 的最简单方法。如果您正在积极地在分支上工作,显然不是答案。
  • @theJones 我不建议重新克隆,因为您会丢失未版本化和忽略文件中的任何更改,例如IDE 项目。以下最受欢迎的答案多年来一直对我有用。

标签: git bash ubuntu version-control grep


【解决方案1】:

删除除您当前签出的分支之外的所有分支:

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

我建议在前几次将git branch -D $b 更改为echo $b,以确保它会删除您想要的分支。

【讨论】:

  • 用这个命令我得到error:branch 'a_branch_name' not found.我可以看到你在做什么,我一直在玩这个命令,但由于某种原因git似乎不喜欢分支名称提供...
  • 嗯。为了帮助排除故障,查看git branch --merged的一些示例输出会很有用
  • 我的分支名称格式为STORY-123-Short-Description
  • 当您运行git branch --merged 时,您会得到一个列表,其中每一行都有一个?
  • 字面意思是error:branch 'a_branch_name' not found.吗?还是它抱怨上面的git branch 输出中的一个分支名称?
【解决方案2】:

'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 编写脚本。为了避免它使用类似的东西:

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

【讨论】:

  • 为我工作;见上文并添加了详细信息。
  • 那么,使用 git 1.7.10 解决了您的问题还是更喜欢直接在 .git 存储库中工作?
  • 如果您收到error:branch 'STORY-123-Short-Description' not found. 错误,这可能是由于 git 颜色设置所致。这对我有用(注意--no-color 选项):git branch --no-color --merged | grep -v \* | xargs git branch -D
  • 我发现唯一可行的 SO 答案。谢谢!
  • 对我不起作用。得到以下错误:fatal: branch name required
【解决方案3】:

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

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

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

【讨论】:

  • 终于有了一个简单实用的选择。我喜欢它:D
  • 如果您已经打包了 refs,或者即使您有时从远程服务器克隆(这将为您提供打包文件),这将不起作用。如果您的 refs 被打包,那么 refs 将不会存储在 .git/refs/heads 中,它们将存储在一个名为“packed-refs”的文件中。见git-scm.com/docs/git-pack-refs
  • 现在删除您已签出的分支似乎是个坏主意
  • @Moberg 只需事先签出一个提交,您分离的 HEAD 就会正常浮动。
【解决方案4】:

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

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

这将删除除 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 解决方案可能更便携,但修剪路径和文件名很棘手,并且可能更容易出错。

【讨论】:

  • 酷。视觉删除:)
【解决方案5】:

我也遇到过类似的情况,最近发现下面的命令很有用。

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 }'`

希望这对某人有所帮助。

【讨论】:

  • 不错,但我需要反引号才能让它工作git branch -D `git branch | awk '{ if ($0 !~ /master/) printf "%s", $0 }'` --实际上我认为你最初确实有它们,但它们在 SO 格式中丢失了。
【解决方案6】:

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

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

就是这样。

【讨论】:

  • 我认为你不能移除你所在的分支。
  • @Dong 该分支旁边有一个 *,因此您只需将其从复制的列表中删除!
【解决方案7】:

我找到了更好的方法in a comment on this issue on github

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

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

【讨论】:

  • 终于,我一直需要的解决方案
  • 我已经尝试过了,但每个分支都会收到error: branch 'my-branch-name' not found.。使用 git 版本 1.8.3.4 (Apple Git-47)。知道为什么吗?
  • 所以。 git for-each-ref --format '%(refname:short)' refs/heads/ | grep -v master | xargs git branch -d
  • 一起学习了 xargs 的用法。谢谢
  • 如果你在 2021 年阅读这篇文章。你很可能会遇到fatal: malformed object name master, fatal: branch name required。这是因为很多 github 项目不再有 master 分支。他们经常改用main。在这种情况下,请将git branch --merged master 替换为git branch --merged main
【解决方案8】:

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

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

非常有用!

【讨论】:

  • 您已经复活了一个古老的线程并发布了与现有线程几乎相同的答案,这是错误的并且缺少它所具有的安全更改。这不是一个好的答案。
  • 这个答案在 git branch 的管道输出中很清楚,修改它,并传递给 git branch -D。不必刻薄。
  • 这个解决方案对我有用。删除了所有本地分支。
  • 这不会删除任何包含“develop_feature”或“master_feature”等单词develop或master的分支。
  • 这是我一直在寻找的答案 ??
【解决方案9】:

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

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

maintainer of git has this to say 关于在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

【讨论】:

  • git branch --no-color 2&gt;/dev/null?
  • 这肯定是一个改进。你总是会遇到需要过滤掉 * 的问题,如果有人从分离的头上运行它,它会很有趣。主要问题是 git branch 是一个瓷器命令,并且不能保证输出在未来的 git 版本中不会改变。
  • 谢谢@AndrewC - 这既回答了神秘的“未找到分支”错误的问题,又使用更合适的命令提供了可行的解决方案! ?
  • 如何识别“Porcelain”和“non-Porcelain”GIT 命令?
  • 默认排除“dev”和“master”可能是一个有用的增强功能?
【解决方案10】:

以下脚本删除分支。使用和修改它需要您自担风险,等等。

根据这个问题的其他答案,我最终为自己编写了一个快速的 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] 

【讨论】:

    【解决方案11】:

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

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

    这将删除所有合并并以feature/bugfix/hotfix/ 开头的本地分支。之后上游远程origin 被修剪(您可能需要输入密码)。

    适用于 Git 1.9.5。

    【讨论】:

      【解决方案12】:

      我编写了一个 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
      

      【讨论】:

        【解决方案13】:

        虽然这不是命令行解决方案,但我很惊讶 Git GUI 还没有被建议。

        我 99% 的时间都在使用命令行,但在这种情况下,它要么太慢(因此是原始问题),要么在诉诸冗长但聪明的方法时,您不知道要删除什么外壳操作。

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

        从 UI 转到 Branch --> DeleteCtrl+单击 要删除的分支,使它们突出显示。如果您想确保它们被合并到一个分支中(例如dev),在Delete Only if Merged Into下将Local Branch设置为dev。否则,将其设置为 始终 以忽略此检查。

        【讨论】:

          【解决方案14】:

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

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

          上面的命令

          1. 列出所有分支
          2. 从列表中忽略主分支并采用其余分支
          3. 删除分支

          【讨论】:

          • 我会先使用git branch | grep -v "master" | xargs git branch -d,这样我就不会删除未合并的分支,只是为了安全起见。但很好的答案!
          • 这是一个powershell版本,@(git branch | Select-String -Pattern "[^(*?)\s? master]") | ForEach-Object{$_.Line.Trim()} | %{git branch -D $_}
          • @baklazan 如果您安装了一些工具,这仅适用于 Windows 10 命令行。你可能有 MINGW 或其他类似的东西,但你不知道。
          【解决方案15】:

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

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

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

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

          【讨论】:

            【解决方案16】:

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

            for /f "tokens=*" %f in ('git branch ^| find /v "*"') do git branch -D %f
            

            【讨论】:

            • 这个工作就像一个魅力!谢谢@kiewic
            • 在 Windows 10 上,当我把它放在 .bat.cmd 文件中时,它说:f was unexpected at this time. 做,我需要更改 %f 参数的一些内容?
            • .cmd 文件中,您需要将%f 替换为%%f
            • 仅供参考,这将删除所有包含“chore”的分支:for /f "tokens=*" %f in ('git branch ^| find "chore"') do git branch -D %f
            【解决方案17】:

            基于此处的多个答案的组合 - 如果您想保留远程上存在的所有分支但删除其余分支,以下 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
            

            【讨论】:

              【解决方案18】:

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

              // hard delete
              
              git branch -D $(git branch)
              

              【讨论】:

              • 这个感觉比进入 .git 和删除东西更安全。
              【解决方案19】:

              对于 powershell,这将起作用:

              git branch --format '%(refname:lstrip=2)' --merged `
                  | Where-Object { $_ -ne 'master' } `
                  | ForEach-Object { git branch -d $_ }
              

              【讨论】:

                【解决方案20】:

                为此,您可以使用git-extras

                $ git delete-merged-branches
                Deleted feature/themes (was c029ab3).
                Deleted feature/live_preview (was a81b002).
                Deleted feature/dashboard (was 923befa).
                

                【讨论】:

                  【解决方案21】:

                  试试下面的shell命令:

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

                  解释:

                  • 通过git branch | grep -v "master"命令获取所有分支(master除外)
                  • 使用xargs 命令选择每个分支
                  • 使用xargs git branch -D 删除分支

                  【讨论】:

                  • 虽然这可能是一个正确的答案。如果没有解释它解决原始问题的内容和方式,那么一行代码并不是很有用。请详细说明您的答案。
                  • 如何使用这一行命令删除除master 和其他一些分支说branchA 之外的所有其他分支?目前我做git branch | grep -v "master" | grep -v "branchA" | xargs git branch -D
                  • 我还要在前面加上git checkout mastergit checkout master; git branch | grep -v "master" | xargs git branch -D
                  【解决方案22】:

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

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

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

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

                  【讨论】:

                  • 已确认:如果不在master 上,此命令将删除master
                  【解决方案23】:

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

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

                  【讨论】:

                    【解决方案24】:

                    如果你想保留 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(远程分支)的分支。删除列表中的所有分支。

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

                    【讨论】:

                      【解决方案25】:

                      如果你想删除所有本地分支,这里是简单的命令:

                      git branch -D `git branch`
                      

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

                      【讨论】:

                      • 愚蠢的我居然试图运行这个无意义的代码
                      • @BarbuBarbu 这个命令没有像这里提到的那样工作吗?我再次在我的机器上运行,它正在按照这里的说明工作。
                      【解决方案26】:

                      如果你使用 NodeJS,我写了this command

                      npx git-clear-branch
                      

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

                      【讨论】:

                      • 最佳答案!
                      【解决方案27】:

                      我推荐一个更温和的答案。这里的许多答案都使用-D,无论更改是否已合并,都会强制删除。这是一个单行,它保留未合并更改的分支。

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

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

                      【讨论】:

                        【解决方案28】:

                        这是适用于在 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()
                        }
                        

                        【讨论】:

                        • 我使用foreach($branch in (git branch)) { if ($branch.trim().startswith("feature")) {git branch -D $branch.trim()} } 删除了我的所有功能。谢谢你:)
                        • 太棒了。谢谢!
                        【解决方案29】:

                        一次删除多个本地分支

                        # 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
                        

                        Source

                        【讨论】:

                          【解决方案30】:
                          git branch -l |grep -v master | xargs git branch -D
                          

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

                          【讨论】:

                            猜你喜欢
                            • 2019-10-30
                            • 2011-04-30
                            • 2021-08-22
                            • 2014-06-09
                            • 2016-10-06
                            • 1970-01-01
                            • 1970-01-01
                            • 2016-01-09
                            • 2013-03-21
                            相关资源
                            最近更新 更多