如何删除已合并的分支?我可以一次删除所有分支,而不是逐个删除每个分支吗?


注意:如果您的工作流可能将master和dev作为祖先,则可以添加其他分支以排除它们。通常我从“sprint-start”标签分支出来,master、dev和qa都不是祖先。


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

git branch --merged

您可能会看到一些不想删除的分支。我们可以添加一些参数来跳过我们不想删除的重要分支,比如master或develop。下面的命令将跳过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中,如果myTopicBranch已合并,则以下命令将不会产生输出(即,您可以删除它)

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

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


我使用以下Ruby脚本删除已经合并的本地和远程分支。如果我对一个有多个遥控器的存储库执行此操作,并且只想从一个遥控器中删除,那么我只需在遥控器列表中添加一个select语句,即可获得所需的遥控器。

#!/usr/bin/env ruby

current_branch = `git symbolic-ref --short HEAD`.chomp
if current_branch != "master"
  if $?.exitstatus == 0
    puts "WARNING: You are on branch #{current_branch}, NOT master."
  else
    puts "WARNING: You are not on a branch"
  end
  puts
end

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}."
else
  puts "This will remove the following branches:"
  puts remote_branches.join("\n")
  puts local_branches.join("\n")
  puts "Proceed?"
  if gets =~ /^y/i
    remote_branches.each do |b|
      remote, branch = b.split(/\//)
      `git push #{remote} :#{branch}`
    end

    # Remove local branches
    `git branch -d #{local_branches.join(' ')}`
  else
    puts "No branches removed."
  end
end

Git Sweep在这方面做得很好。


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

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

UPDATE(通过@oliver;因为不适合注释,但已经有足够的答案了):如果您在分支ABC上,那么ABC将出现在git branch-r--merged的结果中,因为未指定分支,所以分支默认为当前分支,分支始终符合自身合并的条件(因为分支和自身之间没有区别!)。

因此,指定分支:

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

OR第一个结账主机:

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

库布恩的回答没有删除分支名称中包含单词master的分支。以下内容改进了他的回答:

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

当然,它不会删除“master”分支本身:)


基于这些答案,我也制作了自己的Bash脚本来实现这一点!

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

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

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

#!/bin/bash

branch_name="$(git symbolic-ref HEAD 2>/dev/null)" ||
branch_name="(unnamed branch)"     # detached HEAD
branch_name=${branch_name##refs/heads/}

if [[ $branch_name == 'master' ]]; then
   read -r -p "Are you sure? [y/N] " response
   if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]; then
       git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
   fi
else
   echo "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标志告诉您它在做什么。


只是将Adam的答案稍微扩展一点:

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

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

然后,您可以通过简单的git清理来删除所有本地合并分支。


对于那些使用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()}

您需要从这些命令中排除master、main和develop分支。

本地git清除:

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

远程清零:

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

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

git fetch -p

您可以将提交添加到--merged选项。这样,您可以确保只删除合并到原始/主文件中的分支

以下命令将从原点删除合并的分支。

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

您可以测试将删除哪些分支来替换git推送原点--delete with echo

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

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

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

我使用gitbranch-D来避免错误:分支“somebranch”未完全合并。消息,而我的当前签出与主分支不同。


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

这是一篇有助于理解这些命令的文章:Steven Harman的Git Clean:Delete Already Merged Branches。


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

https://gist.github.com/techtonik/b3f0d4b9a56dbacb3afc


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

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

如果要排除master或任何其他分支名称,可以使用PowerShell Select String这样进行管道,并将结果传递给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

假设我有一个名为upstream的远程和一个origin(GitHub风格,我的fork是origin,upstream是upstream)。

我不想从上游删除任何主机、HEAD或任何内容。我也不想删除开发分支,因为这是我们创建PR的公共分支。

列出所有远程分支,按合并的分支进行筛选:

git branch -r

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

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

从引用名称中删除远程名称(origin/somebranch变为somebranch):

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

假设找到要删除的branch1、branch2和branch3:

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的答案。

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

#!/bin/bash

# exclude branches regex, configure as "(branch1|branch2|etc)$"
excludes_default="(master|next|ag/doc-updates)$"
excludes="__NOTHING__"
includes=
merged="--merged"
local=1
remote=1

while [ $# -gt 0 ]; do
  case "$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 ;;
  esac
  shift   # next option
done

if [ "$includes" == "" ]; then
  includes=".*"
else
  includes="($(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" ]; then
  echo "WARNING: You are on branch $current_branch, NOT master."
fi
echo -e "Fetching branches...\n"

git remote update --prune
remote_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" ]; then
  echo "No existing branches have been merged into $current_branch."
else
  echo "This will remove the following branches:"
  if [ "$remote" == 1 -a -n "$remote_branches" ]; then
    echo "$remote_branches"
  fi
  if [ "$local" == 1 -a -n "$local_branches" ]; then
    echo "$local_branches"
  fi
  read -p "Continue? (y/n): " -n 1 choice
  echo
  if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
    if [ "$remote" == 1 ]; then
      remotes=$(git remote)
      # Remove remote branches
      for remote in $remotes
      do
        branches=$(echo "$remote_branches" | grep "$remote/" | sed "s/$remote\/\(.*\)/:\1 /g" | tr -d '\n')
        git push $remote $branches
      done
    fi

    if [ "$local" == 1 ]; then
      # Remove local branches
      locals=$(echo "$local_branches" | sed 's/origin\///g' | tr -d '\n')
      if [ -z "$locals" ]; then
        echo "No branches removed."
      else
        git branch -d $(echo "$locals" | tr -d '\n')
      fi
    fi
  fi
fi

您可以使用git del br工具。

git-del-br -a

您可以使用pip安装它

pip install git-del-br

P.S:我是这个工具的作者。欢迎提出任何建议/反馈。


我使用git流式命名方案,因此这对我来说非常安全:

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

它主要查找以字符串fix/或feature/开头的合并提交。


Adam更新答案的别名版本:

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

通过使用gitrevparse,将获取当前分支名称以排除它。如果出现错误,则意味着没有要删除的本地分支。

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

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

如果您有多个遥控器,请在剪切之前添加grep-origin |,以仅过滤源。

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

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

然后git再次获取远程,并再次使用前面的gitpush-vd命令。

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

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


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

然后做git结账大师。

最后,删除合并的分支。

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git checkout $branchnew
done

git checkout master

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

以下查询适用于我

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管道中的任何给定分支。

在http克隆上运行良好,但在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 -v
  api_doc                  3a05427 [gone] Start of describing the Java API
  bla                      52e080a Update wording.
  branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1
  initial_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)

分支bla和issue_248是将被默默删除的本地分支。

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

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

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

以保护尚未合并的分支。此外,也不需要为master提供保护,因为它在源位置有一个远程,不会显示为已删除。


截至2018.07

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

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

现在,您只需调用git扫描来执行所需的清理。


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

(为便于阅读,拆分为多行)

调用“gitcleanup”将删除已合并到origin/master中的本地分支。它跳过master、staging和dev,因为我们不想在正常情况下删除它们。

将其分解为以下内容:

git-config--全局别名清理这将创建一个名为“cleanup”的全局别名(在所有回购中)这个在命令的开头,我们将使用一些非git命令作为别名的一部分,因此我们需要在这里实际运行bash命令git branch—合并的原始/主此命令返回已合并到原始/master的分支名称列表egrep-v“(^\*|master|staging|dev)”这将从已合并的分支列表中删除master、staging和dev分支。我们不想删除这些分支,因为它们不是功能。xargs git分支-d这将为每个未合并的分支运行gitbranch-d xxxxx命令。这将逐个删除本地分支。


我已经用亚当的答案很多年了。也就是说,在某些情况下,它的行为并没有达到我的预期:

包含单词“master”的分支被忽略,例如“notmaster”或“masterful”,而不仅仅是master分支包含单词“dev”的分支被忽略,例如“dev test”,而不仅仅是dev分支删除可从当前分支的HEAD(即,不一定是主分支)访问的分支在分离HEAD状态下,删除当前提交中可访问的每个分支

1和2很容易解决,只需更改正则表达式。3取决于所需内容的上下文(即仅删除尚未合并到主分支或当前分支的分支)。如果您无意中在分离的HEAD状态下运行,4可能会造成灾难(尽管可以使用git-relog恢复)。

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

TL;博士

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

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

or:

git sweep -f

长而详细的答案

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

通过一次提交创建新的git repo

mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"

创建一些新分支

git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list

酒吧发展食品*船长,船长有驾驭能力的非主人翁

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

原始正则表达式缺少分支“masterful”和“notmaster”:

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

酒吧

使用更新的正则表达式(现在不包括“develop”而不是“dev”):

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

酒吧有驾驭能力的非主人翁

切换到分支foo,进行新的提交,然后根据foo签出新的分支foobar:

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

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

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

酒吧食品有驾驭能力的非主人翁

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

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

酒吧有驾驭能力的非主人翁

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

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

酒吧有驾驭能力的非主人翁

分离的HEAD状态

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

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

酒吧食品脚踏板有驾驭能力的非主人翁

这会删除我刚才打开的分支,“foobar”和“foo”,这几乎肯定不是理想的结果。然而,通过我们修改的命令:

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

酒吧有驾驭能力的非主人翁

一行,包括实际删除

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

全部打包成一个git别名“sweep”:

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

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

git sweep

删除了分支条(为9a56952)。删除了分支masterful(为9a56952)。删除了分支notmaster(为9a56952)。

git sweep -f

已删除分支foo(为2cea1ab)。


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

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

function rmb {
  current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
  if [ "$current_branch" != "master" ]; then
    echo "WARNING: You are on branch $current_branch, NOT master."
  fi
  echo "Fetching merged branches..."
  git remote prune origin
  remote_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" ]; then
    echo "No existing branches have been merged into $current_branch."
  else
    echo "This will remove the following branches:"
    if [ -n "$remote_branches" ]; then
      echo "$remote_branches"
    fi
    if [ -n "$local_branches" ]; then
      echo "$local_branches"
    fi
    read -p "Continue? (y/n): " -n 1 choice
    echo
    if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
      # Remove remote branches
      git push origin `git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$" | sed 's/origin\//:/g' | tr -d '\n'`
      # Remove local branches
      git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
    else
      echo "No branches removed."
    fi
  fi
}

原始来源

这不会删除主分支,而是删除合并的本地和远程分支。一旦你在你的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,您可以使用Windows Powershell或Powershell 7以及Out GridView来创建一个漂亮的分支列表,并用鼠标选择要删除的分支:

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

单击“确定”后,Powershell会将这些分支名称传递给gitbranch-d命令并删除它们


git从git额外回购中删除合并的分支。

https://github.com/tj/git-extras/blob/master/Commands.md#git-删除合并的分支


对于我来说,gitbranch--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

说明:

gitbranch--格式“%(refname:short)”提供本地分支列表gitbranch-r | grep-v HEAD | cut-d/-f2-提供远程分支列表,过滤掉HEADdiff<(…)<(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--合并原始/主|egrep-v“(^\*|master|development)”|cut-b 10-|xargs git push--删除原始

这将删除除主分支和开发分支外的所有合并分支(合并到主分支)。


注意:我对前面的回答不满意,(不在所有系统上工作,不在远程工作,不指定--merged分支,不完全过滤)。所以,我补充了我自己的答案。

主要有两种情况:

地方的

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

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

笔记:

git分支输出--格式“..”是去除空格并允许精确的grep匹配grep-E用于代替egrep,因此它也适用于没有egrep的系统(即:git for windows)。grep-E-v“^master$|^feature/develd$”是指定我不想删除的本地分支xargs-n 1 git branch-d:执行本地分支的删除(它不适用于远程分支)当然,如果您尝试删除当前签出的分支,会出现错误。所以,我建议提前切换到master。

遥远的

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

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

笔记:

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


如果您使用的是带有git插件的OhMyZSH,则可以使用gbda别名。


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

$git分支--合并|grep-v主|xargs-n 1 git分支-D

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


刚刚为此创建了python脚本:

import sys
from shutil import which
import logging
from 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:
            continue
        else:
            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())


要删除合并的分支,gitdelete合并的分支比shell黑客更健壮、更方便。它还检测重基合并和挤压合并。它的自述文件有更多细节。


git工具箱中的git清理脚本

删除所有已合并到主或发展让其他树枝到处乱放。删除时最保守。删除本地和源远程中的分支。


我使用这个:

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

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


我最喜欢的简单脚本:

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

下面创建一个别名gitcleanup,其中包含一个可选参数分支。默认情况下,它使用远程源的默认分支。已合并到此中的每个分支都将被删除。还有一个-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/HEAD
git cleanup master2     # delete all branches that have been merged into master2
git cleanup master2 -d  # do a dryrun (show names of branches that would be delted)

可读代码

谁能读到那句“oneliner”?好了,给你

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;
#

与其他答案有什么不同?

使用--no contains选项过滤掉标识分支(所有其他被删除的分支都已合并到其中的分支),而不是grep-v(如果您特定于分支并指定refs/heads/master,则效果更好)使用远程HEAD检查默认分支名称具有一个参数,用于指定要用作合并主节点的分支具有干式运行选项


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


tl;dr:git branch--format='%(if:notequals=main)%(refname:short)%(then)%(if:notequals=master)%。

看,妈妈,没有工具!

Git可以在不使用外部工具的情况下过滤分支,这意味着有一种跨平台、相对简单的方法可以从搜索中排除默认分支。要列出合并到“main”分支中的分支,不包括“main”分行本身:git branch--format='%(if:notequals=main)%(refname:short)%(then)%(refname:short,%(end)'--merged=main。对于“master”分支:git branch--format='%(如果:notequals=master)%(refname:short)%

我们还可以将两者结合起来,仅当分支名称既不匹配“main”也不匹配“master”时才打印分支名称:git branch--format='%(if:notequals=main)%(refname:short)%(then)%

最后一个附带一个小警告:您应该首先检查默认分支(在本例中为“main”或“master”),因为--merged没有值意味着“merged into HEAD”,它可能指向您要删除的分支之一。但是尝试删除当前的本地分支无论如何都不会起作用,因此如果您正在这样做,这不会有风险。

这种方法的另一个优点是没有多余的前导空格或星号可以过滤掉。

这些命令将为排除的分支打印空行,而不是不打印任何内容,但xargs会处理这一点。如果要使用xargs以外的其他方法处理行,可能需要对空行进行特殊处理(例如通过sed'/^$/d')

有关--format的更多信息,请参阅每个ref的git帮助。