首页 文章

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

提问于
浏览
1434

我有很多Git分支 . 如何删除已合并的分支?是否有一种简单的方法可以删除它们而不是逐个删除它们?

30 回答

  • 74

    你可以使用 git-del-br tool .

    git-del-br -a
    

    您可以通过 pip 使用安装它

    pip install git-del-br
    

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

  • 19

    别名版本的Adam's updated answer

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

    另外,请参阅this answer以获取有关转义复杂别名的方便提示 .

  • 13

    如果您想要删除已经合并到当前分支的所有本地分支,那么我会根据之前的答案提出一个安全命令:

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

    此命令不会影响当前分支或主分支 . 它还会在使用xargs的-t标志之前告诉你它在做什么之前做了什么 .

  • 8

    要删除已合并到主分支的本地分支,我使用以下别名( 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. 消息,而我当前的结账与主分支不同 .

  • 8

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

    如果您需要知道某个分支是否已合并为master,如果myTopicBranch已合并,则以下命令将不会产生任何输出(即您可以将其删除)

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

    您可以使用Git branch命令并解析Bash中的所有分支,并在所有分支上执行 for 循环 . 在此循环中,您可以使用上面的命令检查是否可以删除分支 .

  • 5

    更新:

    如果您的工作流程将其作为可能的祖先,您可以添加其他分支以排除master和dev . 通常我分支出一个“sprint-start”标签和master,dev和qa不是祖先 .

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

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

    您可以看到master和dev被排除在它们是祖先的情况下 .


    您可以删除合并的本地分支:

    git branch -d branchname
    

    如果没有合并,请使用:

    git branch -D branchname
    

    要在旧版本的Git中从远程删除它,请使用:

    git push origin :branchname
    

    在更新版本的Git中使用:

    git push --delete origin branchname
    

    从远程删除分支后,您可以修剪以删除远程跟踪分支:

    git remote prune origin
    

    或者修剪个别远程跟踪分支,正如另一个答案所暗示的那样:

    git branch -dr branchname
    

    希望这可以帮助 .

  • 4

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

    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
    
  • 2

    只是简单地扩展了Adam的答案:

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

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

    然后你可以删除所有本地合并的分支做一个简单的 git cleanup .

  • 4

    这也可以删除除master之外的所有合并分支 .

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

    您将要从这些命令中排除 masterdevelop 分支 .

    本地git清除:

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

    远程git清除:

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

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

    git fetch -p
    
  • 5

    对于那些在Windows上并且更喜欢PowerShell脚本的人来说,这里是一个删除本地合并分支的人:

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

    Git Sweep做得很好 .

  • 63

    您可以将提交添加到--merged选项 . 这样,您可以确保仅删除合并到的分支,即origin / master

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

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

    您可以测试将删除哪些分支替换git push origin --delete with echo

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

    使用Git版本2.5.0:

    git branch -d `git branch --merged`
    
  • 1

    我使用以下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
    
  • 6

    kuboon的回答错过了删除分支名称中包含master一词的分支 . 以下改进了他的答案:

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

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

  • 0

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

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

    GitHub for Windows

  • 2411

    多年来我一直用亚当的答案 . 也就是说,在某些情况下,它没有像我预期的那样行事:

    包含单词"master"的

    • 分支被忽略,例如"notmaster"或"masterful",而不仅仅是主分支
      包含单词"dev"的

    • 分支被忽略,例如"dev-test",而不仅仅是dev分支

    • 删除可从当前分支的HEAD访问的分支(即,不一定是master)

    • 处于分离的HEAD状态,删除当前提交可到达的每个分支

    只需更改正则表达式,即可轻松解决1和2问题 . 3取决于您想要的上下文(即只删除尚未合并到master或当前分支的分支) . 4有可能是灾难性的(虽然可以通过 git reflog 恢复),如果你无意中以分离的HEAD状态运行它 .

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

    TL; DR

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

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

    并使用以下命令调用它:

    git sweep
    

    要么:

    git sweep -f
    

    详尽的答案

    我最简单的方法是使用一些分支和提交来创建一个示例git repo来测试正确的行为:

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

    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
    


    开发
    FOO
    *主人
    高超
    notmaster

    所需行为:选择所有合并的分支,除了:master,develop或current

    原始的正则表达式错过了分支“masterful”和“notmaster”:

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

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

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


    高超
    notmaster

    切换到分支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,如果我重新运行上面的命令列出我要删除的分支,即使它尚未合并到master中,也包含分支“foo”:

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


    FOO
    高超
    notmaster

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

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


    高超
    notmaster

    这只是因为如果没有另外指定, git branch --merged 默认为当前分支的HEAD . 至少在我的工作流程中,我没有被合并为主人,所以我更喜欢以下变体:

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


    高超
    notmaster

    分离的HEAD状态

    依赖于 git branch --merged 的默认行为在分离的HEAD状态中具有更显着的后果:

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


    FOO
    foobar的
    高超
    notmaster

    这将删除我刚才的分支,“foobar”和“foo”,这几乎肯定不是理想的结果 . 但是,通过我们修订的命令:

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


    高超
    notmaster

    一行,包括实际删除

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

    全部包含在git别名“sweep”中:

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

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

    git sweep
    

    删除分支栏(是9a56952) .
    删除分支高手(是9a56952) .
    删除分支notmaster(是9a56952) .

    git sweep -f
    

    删除了分支foo(是2cea1ab) .

  • 1

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

    对于那些希望了解这些命令的人来说,这是一篇有用的文章:Git Clean: Delete Already Merged Branches, by Steven Harman .

  • 11

    请尝试以下命令:

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

    通过使用 git rev-parse 将获得the current branch name以排除它 . 如果您收到错误,则表示没有要删除的本地分支 .

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

    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 fetch 遥控器并再次使用之前的 git push -vd 命令 .

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

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

  • 7

    基于这些答案我做了my own Bash script to do it too

    它使用 git branch --mergedgit branch -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
    }
    
  • 4

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

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

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

  • 4

    以下查询适合我

    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连接不太好 .

  • 3

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

    然后做 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 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
    
  • 13

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

    如果你看一下输出,你会看到类似的东西

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

    分支 blaissue_248 是将以静默方式删除的本地分支 .

    但是你也可以看到单词 [gone] ,它表示已被推送到遥控器(现在已经消失)的分支,因此表示可以删除分支 .

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

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

    保护尚未合并的分支机构 . 也是贪图不需要掌握来保护它,因为它有一个遥远的起源并且不会显示为已经消失 .

  • 352

    为避免从master以外的任何其他分支意外运行命令,请使用以下bash脚本 . 否则,从已关闭master的分支运行 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
    
  • 146

    截至2018.07

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

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

    现在你可以调用 git sweep 来执行所需的清理工作 .

  • 8

    在安装了git bash的Windows上,egrep -v将无法正常工作

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

    其中 grep -E -v 相当于 egrep -v

    使用 -d 删除已经 merged 分支或 -D 删除 unmerged 分支

  • 1

    对于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
    
  • 1

    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

相关问题