如何删除所有已合并的Git分支?

如何删除已经合并的分支?我可以一次全部删除它们,而不是一个接一个地删除每个分支吗?

819913 次浏览

注意:如果你的工作流有可能的祖先,你可以添加其他分支来排除像master和dev这样的分支。通常我从“冲刺开始”标签分支,master、dev和qa不是祖先。


首先,列出在远程中合并的本地跟踪分支(考虑使用-r标志列出所有远程跟踪分支)。

git branch --merged

您可能会看到一些您不想删除的分支。我们可以添加一些参数来跳过我们不想删除的重要分支,例如master或开发。以下命令将跳过master分支和其中包含dev的任何内容。

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

如果要跳过,可以像下面这样将其添加到egrep命令中。分支skip_branch_name不会被删除。

git branch --merged| egrep -v "(^\*|master|main|dev|skip_branch_name)"

要删除已合并到当前签出分支中的所有本地分支:

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

您可以看到master和dev被排除在外,以防它们是祖先。


您可以使用以下命令删除合并的本地分支:

git branch -d branchname

如果没有合并,请使用:

git branch -D branchname

要从远程使用中删除它:

git push --delete origin branchname
git push origin :branchname    # for really old git

从远程删除分支后,您可以使用以下命令修剪以摆脱远程跟踪分支:

git remote prune origin

或修剪单个远程跟踪分支,如另一个答案所示,使用:

git branch -dr branchname

Git中没有命令可以自动为您执行此操作。但是您可以编写一个使用Git命令为您提供所需内容的脚本。这可以通过多种方式完成,具体取决于您使用的分支模型。

如果您需要知道分支是否已合并到master中,如果myTopic分支已合并(即您可以删除它),则以下命令将不会产生输出

$ git rev-list master | grep $(git rev-parse myTopicBranch)

您可以使用Git分支命令并解析出Bash中的所有分支并对所有分支执行for循环。在这个循环中,您可以使用上述命令检查是否可以删除分支。

我使用下面的Ruby脚本来删除我已经合并的本地和远程分支。如果我正在为具有多个遥控器的存储库执行此操作并且只想从一个中删除,我只需将选择语句添加到遥控器列表以仅获取我想要的遥控器。

#!/usr/bin/env ruby
current_branch = `git symbolic-ref --short HEAD`.chompif current_branch != "master"if $?.exitstatus == 0puts "WARNING: You are on branch #{current_branch}, NOT master."elseputs "WARNING: You are not on a branch"endputsend
puts "Fetching merged branches..."remote_branches= `git branch -r --merged`.split("\n").map(&:strip).reject {|b| b =~ /\/(#{current_branch}|master)/}
local_branches= `git branch --merged`.gsub(/^\* /, '').split("\n").map(&:strip).reject {|b| b =~ /(#{current_branch}|master)/}
if remote_branches.empty? && local_branches.empty?puts "No existing branches have been merged into #{current_branch}."elseputs "This will remove the following branches:"puts remote_branches.join("\n")puts local_branches.join("\n")puts "Proceed?"if gets =~ /^y/iremote_branches.each do |b|remote, branch = b.split(/\//)`git push #{remote} :#{branch}`end
# Remove local branches`git branch -d #{local_branches.join(' ')}`elseputs "No branches removed."endend

扫一扫在这方面做得很好。

这也适用于删除除master之外的所有合并分支。

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d

要删除远程上已合并的所有分支:

git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin

在最新版本的Git中

git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin

更新(由@oliver;因为不适合评论,但已经有足够的答案了):如果您在分支ABC上,则ABC将出现在git branch -r --merged的结果中,因为该分支未指定,因此分支默认为当前分支,并且分支始终符合合并到自身的条件(因为分支与自身之间没有差异!)。

所以要么指定分支:

git branch -r --merged master | grep -v master ...

或第一结帐大师:

git checkout master | git branch -r --merged | grep -v ...

kuboon的回答没有删除分支名称中有master字样的分支。以下是他的回答:

git branch -r --merged | grep -v "origin/master$" | sed 's/\s*origin\///' | xargs -n 1 git push --delete origin

当然,它并没有删除“master”分支本身:)

基于这些答案,我做了我自己的Bash脚本也能做到

它使用git branch --mergedgit branch -d删除已合并的分支,并在删除之前提示您输入每个分支。

merged_branches () {local current_branch=$(git rev-parse --abbrev-ref HEAD)for branch in $(git branch --merged | cut -c3-)doecho "Branch $branch is already merged into $current_branch."echo "Would you like to delete it? [Y]es/[N]o "read REPLYif [[ $REPLY =~ ^[Yy] ]]; thengit branch -d $branchfidone}

为了避免意外地从master以外的任何其他分支运行命令,我使用以下bash脚本。否则,从已与off master合并的分支运行git branch --merged | grep -v "\*" | xargs -n 1 git branch -d可能会删除master分支。

#!/bin/bash
branch_name="$(git symbolic-ref HEAD 2>/dev/null)" ||branch_name="(unnamed branch)"     # detached HEADbranch_name=${branch_name##refs/heads/}
if [[ $branch_name == 'master' ]]; thenread -r -p "Are you sure? [y/N] " responseif [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; thengit branch --merged | grep -v "\*" | xargs -n 1 git branch -dfielseecho "Refusing to delete branches that are not merged into '$branch_name'. Checkout master first."fi

如果您想删除所有已经合并到您当前所在分支的本地分支,那么我根据前面的答案提出了一个安全的命令来执行此操作:

git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d

此命令不会影响您当前的分支或主分支。它还会在执行之前告诉您它在做什么,使用xargs的-t标志。

把亚当的回答稍微延伸一下:

通过运行git config -e --global将其添加到您的Git配置中

[alias]cleanup = "!git branch --merged | grep  -v '\\*\\|master\\|develop' | xargs -n 1 -r git branch -d"

然后您可以执行简单的git cleanup删除所有本地合并分支。

对于那些使用Windows并喜欢PowerShell脚本的人来说,这里有一个删除本地合并分支的脚本:

function Remove-MergedBranches{git branch --merged |ForEach-Object { $_.Trim() } |Where-Object { $_ -NotMatch "^\*" } |Where-Object { -not ( $_ -Like "*master" -or $_ -Like "*main" ) } |ForEach-Object { git branch -d $_ }}

或者简短的版本:

git branch --merged | %{$_.trim()}  | ?{$_ -notmatch 'dev' -and $_ -notmatch 'master' -and $_ -notmatch 'main'} | %{git branch -d $_.trim()}

您需要从这些命令中排除mastermaindevelop分支。

本地git清除:

git branch --merged | grep -v '\*\|master\|main\|develop' | xargs -n 1 git branch -d

远程git清除:

git branch -r --merged | grep -v '\*\|master\|main\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin

同步远程分支的本地注册表:

git fetch -p

您可以将提交添加到--合并选项。通过这种方式,您可以确保只删除合并到源/主

中的分支

以下命令将从您的源中删除合并的分支。

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete

您可以测试哪些分支将被删除,替换git推送源--deletewith echo

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo

要删除已合并到master分支的本地分支,我使用以下别名(git config -e --global):

cleanup = "!git branch --merged master | grep -v '^*\\|master' | xargs -n 1 git branch -D"

我使用git branch -D来避免error: The branch 'some-branch' is not fully merged.消息,而我当前的结帐与主分支不同。

git branch --merged | grep -Ev '^(. master|\*)' | xargs -n 1 git branch -d将删除除当前签出分支和/或master之外的所有本地分支。

这里有一篇对那些希望理解这些命令的人很有帮助的文章:Git Clean:删除已经合并的分支,作者Steven Harman

Windoze友好的Python脚本(因为git-sweep在Wesnoth存储库上窒息):

#!/usr/bin/env python# Remove merged git branches. Cross-platform way to execute:##   git branch --merged | grep -v master | xargs git branch -d## Requires gitapi - https://bitbucket.org/haard/gitapi# License: Public Domain
import gitapi
repo = gitapi.Repo('.')output = repo.git_command('branch', '--merged').strip()for branch in output.split('\n'):branch = branch.strip()if branch.strip(' *') != 'master':print(repo.git_command('branch', '-d', branch).strip())

如何在PowerShell控制台中删除合并的分支

git branch --merged | %{git branch -d $_.Trim()}

如果您想排除大师或任何其他分支名称,您可以像这样使用PowerShell选择字符串管道并将结果传递给git branch -d

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})

如果您使用HubFlow或GitFlow等分支模型,您可以使用此命令删除合并的功能分支:

git branch --merged | grep feature.* | grep -v "\*" | xargs -n 1 git branch -d

假设我有一个名为上游的遥控器和一个原点(GitHub风格,我的分叉是原点,上游是上游)。

我不想删除上游的任何主机、HEAD或任何东西。我也不想删除开发分支,因为这是我们创建PR的常见分支。

列出所有远程分支,按合并的分支过滤:

git branch -r

从该列表中删除包含我知道在我不想删除的分支名称中的单词的行:

sed '/develop\|master\|HEAD\|upstream/d'

从引用名称中删除远程名称(起源/某个分支变为某个分支):

sed 's/.*\///'

使用xargs调用单行代码:

xargs git push --delete origin

把它放在一起,你会得到:

git branch -r --merged | sed '/develop\|master\|HEAD\|upstream/d' |  sed 's/.*\///' | xargs git push --delete origin

这将使我只剩下一些我已经处理过但尚未合并的分支。然后您可以一个接一个地删除它们,因为不应该有太多。

查找您不再需要的分支:

git branch -ar

假设您找到要删除的分支1、分支2和分支3:

git push --delete origin branch1 branch2 branch3

使用Git版本2.5.0:

git branch -d `git branch --merged`

如果您希望删除已合并的本地分支并删除它们的远程分支,这里是我更喜欢的一行代码:

git branch --merged | xargs -I_br -- sh -c 'git branch -d _br; git push origin --delete _br'

我的Bash脚本贡献松散地基于mmrobin的回答

它需要一些有用的参数来指定包含和排除,或者只检查/删除本地或远程分支而不是两者。

#!/bin/bash
# exclude branches regex, configure as "(branch1|branch2|etc)$"excludes_default="(master|next|ag/doc-updates)$"excludes="__NOTHING__"includes=merged="--merged"local=1remote=1
while [ $# -gt 0 ]; docase "$1" in-i) shift; includes="$includes $1" ;;-e) shift; excludes="$1" ;;--no-local) local=0 ;;--no-remote) remote=0 ;;--all) merged= ;;*) echo "Unknown argument $1"; exit 1 ;;esacshift   # next optiondone
if [ "$includes" == "" ]; thenincludes=".*"elseincludes="($(echo $includes | sed -e 's/ /|/g'))"fi
current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')if [ "$current_branch" != "master" ]; thenecho "WARNING: You are on branch $current_branch, NOT master."fiecho -e "Fetching branches...\n"
git remote update --pruneremote_branches=$(git branch -r $merged | grep -v "/$current_branch$" | grep -v -E "$excludes" | grep -v -E "$excludes_default" | grep -E "$includes")local_branches=$(git branch $merged | grep -v "$current_branch$" | grep -v -E "$excludes" | grep -v -E "$excludes_default" | grep -E "$includes")if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; thenecho "No existing branches have been merged into $current_branch."elseecho "This will remove the following branches:"if [ "$remote" == 1 -a -n "$remote_branches" ]; thenecho "$remote_branches"fiif [ "$local" == 1 -a -n "$local_branches" ]; thenecho "$local_branches"firead -p "Continue? (y/n): " -n 1 choiceechoif [ "$choice" == "y" ] || [ "$choice" == "Y" ]; thenif [ "$remote" == 1 ]; thenremotes=$(git remote)# Remove remote branchesfor remote in $remotesdobranches=$(echo "$remote_branches" | grep "$remote/" | sed "s/$remote\/\(.*\)/:\1 /g" | tr -d '\n')git push $remote $branchesdonefi
if [ "$local" == 1 ]; then# Remove local brancheslocals=$(echo "$local_branches" | sed 's/origin\///g' | tr -d '\n')if [ -z "$locals" ]; thenecho "No branches removed."elsegit branch -d $(echo "$locals" | tr -d '\n')fifififi

您可以使用git-del-br工具

git-del-br -a

您可以使用pip安装它

pip install git-del-br

P. S:我是这个工具的作者,欢迎大家给我任何建议和反馈。

我使用git-flow esque命名方案,所以这对我来说非常安全:

git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d

它基本上查找以字符串fix/feature/开头的合并提交。

别名版本亚当的最新答案

[alias]branch-cleanup = "!git branch --merged | egrep -v \"(^\\*|master|dev)\" | xargs git branch -d #"

此外,有关转义复杂别名的便捷提示,请参阅这个答案

尝试以下命令:

git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

通过使用git rev-parse将获得当前分支名称以排除它。如果您收到错误,这意味着没有本地分支要删除。

要对远程分支执行相同的操作(用您的远程名称更改origin),请尝试:

git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)

如果您有多个遥控器,请在cut之前添加grep origin |以仅过滤origin

如果上述命令失败,请先尝试删除合并的远程跟踪分支:

git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

然后再次git fetch遥控器并再次使用之前的git push -vd命令。

如果您经常使用它,请考虑将其作为别名添加到~/.gitconfig文件中。

如果您错误地删除了一些分支,请使用git reflog查找丢失的提交。

编写一个脚本,其中Git检查出所有已合并到master的分支。

然后做git checkout master

最后,删除合并的分支。

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); dobranchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")echo branch-name: $branchnewgit checkout $branchnewdone
git checkout master
for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); dobranchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")echo branch-name: $branchnewgit push origin --delete $branchnewdone

下面的查询对我有用

for branch in  `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print$1}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done

这将过滤grep管道中的任何给定分支。

适用于超文本传输协议克隆,但不适用于ssh连接。

在安装了gitbash的Windows上,egrep-v将无法工作

git branch --merged | grep -E -v "(master|test|dev)" | xargs git branch -d

其中grep -E -v等价于egrep -v

使用-d删除已经合并的分支或-D删除未合并个分支

接受的解决方案非常好,但有一个问题,即它还删除了尚未合并到远程的本地分支。

如果您查看输出,您将看到类似的内容

$ git branch --merged master -vapi_doc                  3a05427 [gone] Start of describing the Java APIbla                      52e080a Update wording.branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1initial_proposal         6e59fb0 [gone] Original proposal, converted to AsciiDoc.issue_248                be2ba3c Skip unit-for-type checking. This needs more work. (#254)master                   be2ba3c Skip unit-for-type checking. This needs more work. (#254)

分支blaissue_248是本地分支,将被静默删除。

但是您也可以看到单词[gone],它表示已被推送到远程的分支(现在已经消失),因此表示可以删除分支。

因此,原始答案可以更改为(为较短的行长度拆分为多行)

git branch --merged master -v | \grep  "\\[gone\\]" | \sed -e 's/^..//' -e 's/\S* .*//' | \xargs git branch -d

以保护尚未合并的分支。此外,主的greping保护它,是不需要的,因为这有一个远程在原点,并没有显示为消失。

截至2018.07

将其添加到~/.gitconfig[alias]部分:

sweep = !"f() { git branch --merged | egrep -v \"(^\\*|master|dev)\" || true | xargs git branch -d; }; f"

现在您可以调用git sweep来执行所需的清理。

$ git config --global alias.cleanup'!git branch --merged origin/master | egrep -v "(^\*|master|staging|dev)" | xargs git branch -d'

(为了易读性,分成多行)

调用“git清理”将删除已经合并到源/主中的本地分支。它会跳过主、暂存和开发,因为我们不想在正常情况下删除这些分支。

分解一下,这就是它正在做的事情:

  1. git config --global alias.cleanup
    • 这是创建一个名为“清理”的全局别名(跨所有存储库)
  2. 命令开头的!表示我们将使用一些非git命令作为此别名的一部分,因此我们需要在此处实际运行bash命令
  3. git branch --merged origin/master
    • 此命令返回已合并到origin/master中的分支名称列表
  4. egrep -v "(^\*|master|staging|dev)"
    • 这将从已合并的分支列表中删除master、stage和dev分支。我们不想删除这些分支,因为它们不是功能。
  5. xargs git branch -d
    • 这将为每个未合并的分支运行git branch -d xxxxx命令。这将逐个删除本地分支。

我已经使用Adam的答案很多年了。也就是说,在某些情况下,它的行为并不像我预期的那样:

  1. 忽略包含单词“master”的分支,例如“not master”或“master ful”,而不仅仅是master分支
  2. 包含单词“dev”被忽略的分支,例如“dev-test”,而不仅仅是dev分支
  3. 删除可从当前分支的HEAD到达的分支(即不一定是master)
  4. 在分离的HEAD状态下,从当前提交中删除分支

1和2很容易解决,只需更改正则表达式。3取决于您想要的上下文(即仅删除尚未合并到master或针对当前分支的分支)。4有可能是灾难性的(尽管可以用git reflog恢复),如果你无意中在分离的HEAD状态下运行它。

最后,我希望这一切都在一个不需要单独(Bash|Ruby|Python)脚本的单行代码中。

太长别读

创建一个接受可选-f标志的git别名“扫描”:

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \| xargs git branch -d'

并调用它:

git sweep

或:

git sweep -f

冗长而详细的回答

对我来说,创建一个带有一些分支和提交的示例git repo来测试正确的行为是最简单的:

使用单个提交创建一个新的git仓库

mkdir sweep-test && cd sweep-test && git initecho "hello" > hellogit add . && git commit -am "initial commit"

创建一些新分支

git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterfulgit branch --list
  bardevelopfoo* mastermasterfulnotmaster

期望的行为:选择所有合并的分支,除了:master、开发或当前

原始的regex忽略了分支“大师”和“Notmaster”:

git checkout foogit branch --merged | egrep -v "(^\*|master|dev)"
  bar

使用更新的regex(现在不包括“开发”而不是“开发”):

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
barmasterfulnotmaster

切换到分支foo,进行新的提交,然后签出一个基于foo的新分支fobar:

echo "foo" > foogit add . && git commit -am "foo"git checkout -b foobarecho "foobar" > foobargit add . && git commit -am "foobar"

我当前的分支是fobar,如果我重新运行上面的命令列出我想删除的分支,分支“foo”即使没有合并到master中也会包含在内:

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  barfoomasterfulnotmaster

但是,如果我在master上运行相同的命令,则不包括分支“foo”:

git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  barmasterfulnotmaster

这仅仅是因为如果没有另外指定,git branch --merged默认为当前分支的HEAD。至少对于我的工作流,我不想删除本地分支,除非它们已合并到master,所以我更喜欢以下变体使用git reg-parse

git checkout foobargit branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  barmasterfulnotmaster

分离HEAD状态

依赖git branch --merged的默认行为在分离的HEAD状态下会产生更严重的后果:

git checkout foobargit checkout HEAD~0git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  barfoofoobarmasterfulnotmaster

这将删除我刚刚访问的分支,“foo”和“foo”,这几乎肯定不是预期的结果。但是,我们修改了命令:

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  barmasterfulnotmaster

一行,包括实际删除

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d

所有这些都包装成一个git别名“扫描”:

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \| xargs git branch -d'

别名接受可选的-f标志。默认行为是仅删除已合并到master的分支,但-f标志将删除已合并到当前分支的分支。

git sweep
Deleted branch bar (was 9a56952).Deleted branch masterful (was 9a56952).Deleted branch notmaster (was 9a56952).
git sweep -f
Deleted branch foo (was 2cea1ab).

我一直在使用以下方法在一个cmd中删除合并的本地和远程分支

我的bashrc文件中有以下内容:

function rmb {current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')if [ "$current_branch" != "master" ]; thenecho "WARNING: You are on branch $current_branch, NOT master."fiecho "Fetching merged branches..."git remote prune originremote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; thenecho "No existing branches have been merged into $current_branch."elseecho "This will remove the following branches:"if [ -n "$remote_branches" ]; thenecho "$remote_branches"fiif [ -n "$local_branches" ]; thenecho "$local_branches"firead -p "Continue? (y/n): " -n 1 choiceechoif [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then# Remove remote branchesgit push origin `git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$" | sed 's/origin\//:/g' | tr -d '\n'`# Remove local branchesgit branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`elseecho "No branches removed."fifi}

原创来源

这不会删除主分支,而是删除合并的本地和远程分支。一旦您的rc文件中有了这个,只需运行rmb,您将看到一个合并分支的列表,这些分支将被清理并要求确认操作。您可以修改代码以不要求确认,但最好保留它。

对于Windows,您可以使用以下命令安装Cygwin并删除所有远程分支:

git branch -r --merged | "C:\cygwin64\bin\grep.exe" -v master | "C:\cygwin64\bin\sed.exe" 's/origin\///' | "C:\cygwin64\bin\xargs.exe" -n 1 git push --delete origin

如果您使用的是Windows,您可以使用带有Out-GridView的Windows Powershell或Powershell 7来创建一个不错的分支列表,然后用鼠标选择要删除的分支:

git branch --format "%(refname:short)" --merged  | Out-GridView -PassThru | % { git branch -d $_ }

在此处输入图像描述单击OK后,Powershell会将此分支名称传递给git branch -d命令并删除它们输入图片描述

对我来说,git branch --merged没有显示通过GitHub PR合并的分支。我不确定原因,但我使用以下行删除没有远程跟踪分支的所有本地分支

diff <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | grep '<' | cut -c 3- | xargs git branch -D

说明:

  • git branch --format "%(refname:short)"给出了一个本地分支列表
  • git branch -r | grep -v HEAD | cut -d/ -f2-给出了一个远程分支列表,过滤掉HEAD
  • diff <(...) <(...)给出括号内两个命令的输出差异
  • grep '<'过滤存在于第一个列表中但不存在于第二个列表中的分支
  • cut -c 3-给出从第3个字符开始的行,从而删除前缀<
  • xargs git branch -D对每个分支名称执行git branch -D

或者,您可以像这样避免grep -v '<'

diff --old-line-format="%L" --new-line-format="" --unchanged-line-format="" <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | xargs git branch -D

如果要删除合并的分支,则只需要删除远程跟踪分支,除非另有说明。

因此,要删除这些分支,您可以通过

git branch --remote --merged origin/master | egrep -v "(^\*|master|development)" | cut -b 10- | xargs git push --delete origin

这将删除除masterdevelopment之外的所有合并分支(合并到master)。

说明:我对以前的答案不满意,(不能在所有系统上工作,不能在远程工作,不能指定--合并分支,不能准确过滤)。所以,我添加了自己的答案。

主要有两个案例:

当地

您希望删除本地分支已经合并到另一个本地分支。在删除过程中,您希望保留一些重要的分支,如master、开发等。

git branch --format "%(refname:short)" --merged master | grep -E -v '^master$|^feature/develop$' | xargs -n 1 git branch -d

备注

  • git branch output --format"…"是去掉空白并允许精确的grep匹配
  • grep -E用于而不是egrep,因此它也适用于没有egrep的系统(即:Windows的git)。
  • grep -E -v '^master$|^feature/develop$'是指定我不想删除的本地分支
  • xargs -n 1 git branch -d:删除本地分支(它不适用于远程分支)
  • 当然如果您尝试删除当前签出的分支,您会收到错误。所以,我建议事先切换到master。

远程

您希望删除远程分支已合并到另一个远程分支。在删除过程中,您希望保留一些重要的分支,如HEAD、master、发行版等。

git branch -r --format "%(refname:short)" --merged origin/master | grep -E -v '^*HEAD$|^*/master$|^*release' | cut -d/ -f2- | xargs -n 1 git push --delete origin

备注

  • 对于远程,我们使用-r选项并提供完整的分支名称origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release'是匹配我们不想删除的远程分支。
  • cut -d/ -f2-:删除不需要的“来源/”前缀,否则将由git branch命令打印出来。
  • xargs -n 1 git push --delete origin:执行删除远程分支。

如果您将OhMyZSHgit插件一起使用,则可以使用gbda别名。

我发现最简单的方法是只删除本地分支,而不是远程分支:

$ git branch --merged | grep -v master | xargs -n 1 git branch -D

此命令将仅删除已合并在主分支中的分支。如果您不想删除其他分支,例如staging,请小心。

为此创建了python脚本:

import sysfrom shutil import whichimport loggingfrom subprocess import check_output, call
logger = logging.getLogger(__name__)
if __name__ == '__main__':if which("git") is None:logger.error("git is not found!")sys.exit(-1)
branches = check_output("git branch -r --merged".split()).strip().decode("utf8").splitlines()current = check_output("git branch --show-current".split()).strip().decode("utf8")blacklist = ["master", current]
for b in branches:b = b.split("/")[-1]
if b in blacklist:continueelse:if input(f"Do you want to delete branch: '{b}' [y/n]\n").lower() == "y":call(f"git branch -D {b}".split())call(f"git push --delete origin {b}".split())

要删除合并的分支,g it-删除-合并-分支比shell hack更健壮、更方便。它还检测rebase合并和squash合并。它的自述文件有更多细节

#0来自git工具带的脚本

删除所有已经合并到master或发展。保持其他分支躺在周围。将是最保守的删除。

删除本地和远程源中的分支。

我用这个:

git branch --delete $(git branch --format '%(refname:short)' --merged | grep --invert-match 'main\|master\|branch-to-skip')

它列出了所有以指定格式合并的分支,然后将该列表提供给git分支--delet。

我最喜欢的简单脚本:

git branch --merged | grep -E -v "(master|main|develop|other)" | xargs git branch -d

下面创建了一个带有一个可选参数分支的别名git cleanup。默认情况下,它使用远程源的默认分支。已合并到其中的每个分支都将被删除。还有一个-d/--dryrun选项来显示将删除的内容。

设置

git config --global alias.cleanup '!COMMAND="git branch -D"; while [[ $# -gt 0 ]]; do case "$1" in -d|--dryrun) COMMAND="echo"; shift; ;; *) MAIN_BRANCH="$1"; shift;; esac; done; MAIN_BRANCH="${MAIN_BRANCH:-$(git symbolic-ref refs/remotes/origin/HEAD)}"; git for-each-ref --merged="$MAIN_BRANCH" --no-contains="$MAIN_BRANCH" --format="%(refname:short)" refs/heads/ | xargs -n1 -r $COMMAND;#'

用法:

git cleanup             # delete all branches that have been merged into origin/HEADgit cleanup master2     # delete all branches that have been merged into master2git cleanup master2 -d  # do a dryrun (show names of branches that would be delted)

可读代码

谁能看懂那个"单线"?给你

COMMAND="git branch -D";while [[ $# -gt 0 ]]; docase "$1" in-d|--dryrun)COMMAND="echo";shift;;;*)MAIN_BRANCH="$1";shift;;esac;done;MAIN_BRANCH="${MAIN_BRANCH:-$(git symbolic-ref refs/remotes/origin/HEAD)}";git for-each-ref --merged="$MAIN_BRANCH" --no-contains="$MAIN_BRANCH" --format="%(refname:short)" refs/heads/ | xargs -n1 -r $COMMAND;#

与其他答案有什么不同?

  • 使用--no-contains选项过滤掉标识分支(所有其他被删除的分支都已合并到其中的分支)而不是grep -v(如果您对分支有特定要求并指定refs/head/master,则效果更好)
  • 使用远程HEAD检查默认分支名称
  • 有一个参数来指定使用哪个分支作为合并主
  • 有一个Dryrun选项

我使用一个Python脚本,它自动执行大多数流行的答案的步骤,并检查剩余的分支,看看它们是否会在合并时产生任何更改,如果没有,则交互式提示删除它们:https://github.com/robertknight/prune-merged-branches