How can I delete all Git branches which have been merged?
我有很多Git分支。如何删除已合并的分支?是否有一种简单的方法可以将它们全部删除而不是逐个删除?
更新:
如果您的工作流将其他分支作为可能的祖先,则可以添加其他要排除的分支,如master和dev。通常我从"sprint start"标签和master分支,dev和qa不是祖先。
首先,列出在远程中合并的所有分支。
1 | git branch --merged |
您可能会看到一些不想删除的分支。我们可以添加一些参数来跳过我们不想像master或developer那样删除的重要分支。下面的命令将跳过主分支以及其中包含dev的任何内容。
1 | git branch --merged| egrep -v"(^\*|master|dev)" |
号
如果要跳过,可以将其添加到egrep命令中,如下所示。分支
1 | git branch --merged| egrep -v"(^\*|master|dev|skip_branch_name)" |
要删除已合并到当前签出分支的所有本地分支,请执行以下操作:
1 | git branch --merged | egrep -v"(^\*|master|dev)" | xargs git branch -d |
。
您可以看到master和dev被排除在外,以防它们是祖先。
可以删除合并的本地分支:
1 | git branch -d branchname |
如果未合并,请使用:
1 | git branch -d branchname |
要在旧版本的git中从远程删除它,请使用:
1 | git push origin :branchname |
。
在最新版本的git use中:
1 | git push --delete origin branchname |
从远程删除分支后,可以通过以下方式进行修剪以除去远程跟踪分支:
1 | git remote prune origin |
。
或者修剪单独的远程跟踪分支,如另一个答案所示,使用:
1 | git branch -dr branchname |
希望这有帮助。
要删除远程上已合并的所有分支,请执行以下操作:
1 | git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin |
号
在Git的最新版本中
1 | git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin |
号
只是把亚当的回答再延伸一点:
通过运行
1 2 | [alias] cleanup ="!git branch --merged | grep -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d" |
号
然后您可以删除所有本地合并的分支,只需执行一个简单的
这也可以删除除master之外的所有合并分支。
1 | git branch --merged | grep -v '^* master$' | grep -v '^ master$' | xargs git branch -d |
号
您将希望从这些命令中排除
本地git清除:
1 | git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d |
远程git清除:
1 | git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin |
号
同步远程分支的本地注册表:
1 | git fetch -p |
对于那些在Windows上并且更喜欢PowerShell脚本的用户,以下是一个删除本地合并分支的脚本:
1 2 3 4 5 6 7 8 | function Remove-MergedBranches { git branch --merged | ForEach-Object { $_.Trim() } | Where-Object {$_ -NotMatch"^\*"} | Where-Object {-not ( $_ -Like"*master" )} | ForEach-Object { git branch -d $_ } } |
我用亚当的答案已经很多年了。也就是说,在某些情况下,它的行为并不像我预期的那样:
1&2非常简单,只需更改regex即可。3取决于所需内容的上下文(即只删除尚未合并到master或与当前分支相对应的分支)。4有可能是灾难性的(虽然可以用
最后,我希望这一切都在一个不需要单独(bash ruby python)脚本的单行程序中。
DR创建一个Git别名"sweep",接受可选的
1 2 3 | git config --global alias.sweep '!git branch --merged $([[ $1 !="-f" ]] \ && git rev-parse master) | egrep -v"(^\*|^\s*(master|develop)$)" \ | xargs git branch -d' |
并调用它:
1 | git sweep |
号
或:
1 | git sweep -f |
详细而漫长的答案
对于我来说,用一些分支创建一个git repo示例是最简单的,并承诺测试正确的行为:
用一次提交创建一个新的git repo1 2 3 | mkdir sweep-test && cd sweep-test && git init echo"hello"> hello git add . && git commit -am"initial commit" |
。创建一些新分支
1 2 | git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful git branch --list |
1
2
3
4
5
6 bar
develop
foo
* master
masterful
notmaster
号所需行为:选择除"主"、"开发"或"当前"之外的所有合并分支
原始regex缺少分支"masterful"和"notmaster":
1 2 | git checkout foo git branch --merged | egrep -v"(^\*|master|dev)" |
。
1 bar
号
使用更新的regex(现在不包括"develop"而不是"dev"):
1 | git branch --merged | egrep -v"(^\*|^\s*(master|develop)$)" |
。
1
2
3 bar
masterful
notmaster
号切换到分支foo,进行新的提交,然后根据foo签出新的分支foobar:
1 2 3 4 5 | 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中,也会包含在其中:
1 | git branch --merged | egrep -v"(^\*|^\s*(master|develop)$)" |
。
1
2
3
4 bar
foo
masterful
notmaster
号
但是,如果我在master上运行相同的命令,则不包括分支"foo":
1 | git checkout master && git branch --merged | egrep -v"(^\*|^\s*(master|develop)$)" |
1
2
3 bar
masterful
notmaster
号
这仅仅是因为
1 2 | git checkout foobar git branch --merged $(git rev-parse master) | egrep -v"(^\*|^\s*(master|develop)$)" |
。
1
2
3 bar
masterful
notmaster
号分离头状态
依赖于
1 2 3 | git checkout foobar git checkout HEAD~0 git branch --merged | egrep -v"(^\*|^\s*(master|develop)$)" |
号
1
2
3
4
5 bar
foo
foobar
masterful
notmaster
号
这将删除我刚才所在的分支,"foobar"和"foo",这几乎肯定不是期望的结果。但是,根据我们修订的命令:
1 | git branch --merged $(git rev-parse master) | egrep -v"(^\*|^\s*(master|develop)$)" |
号
1
2
3 bar
masterful
notmaster
号一行,包括实际删除
1 | git branch --merged $(git rev-parse master) | egrep -v"(^\*|^\s*(master|develop)$)" | xargs git branch -d |
号全部打包成一个git别名"sweep":
1 2 3 | git config --global alias.sweep '!git branch --merged $([[ $1 !="-f" ]] \ && git rev-parse master) | egrep -v"(^\*|^\s*(master|develop)$)" \ | xargs git branch -d' |
别名接受可选的
1 | git sweep |
号
1
2
3 Deleted branch bar (was 9a56952).
Deleted branch masterful (was 9a56952).
Deleted branch notmaster (was 9a56952).
号
1 | git sweep -f |
1 Deleted branch foo (was 2cea1ab).
号
Git Sweep在这方面做得很好。
使用Git 2.5.0版:
1 | git branch -d `git branch --merged` |
号
您可以向--merged选项添加commit。这样,您可以确保只删除合并到其中的分支,即源站/主服务器
以下命令将从原点删除合并的分支。
1 | git branch -r --merged origin/master | grep -v"^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete |
。
您可以测试哪些分支将被删除,替换git push-origin——用echo删除
1 | git branch -r --merged origin/master | grep -v"^.*master" | sed s:origin/:: |xargs -n 1 echo |
我使用下面的Ruby脚本删除已经合并的本地和远程分支。如果我是为一个具有多个远程的存储库而做的,并且只想从其中删除一个,那么我只需向远程列表添加一个select语句,以仅获取我想要的远程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #!/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(" "). map(&:strip). reject {|b| b =~ /\/(#{current_branch}|master)/} local_branches= `git branch --merged`. gsub(/^\* /, ''). split(" "). 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(" ") puts local_branches.join(" ") 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 |
号
如何在PowerShell控制台中删除合并的分支
1 | git branch --merged | %{git branch -d $_.Trim()} |
如果要排除master或任何其他分支名称,可以使用PowerShell select字符串进行管道连接,并将结果传递给
1 | git branch -d $(git branch --merged | Select-String -NotMatch"master" | %{$_.ToString().Trim()}) |
。
在git中没有自动为您执行此操作的命令。但您可以编写一个脚本,使用git命令来提供所需的内容。根据您使用的分支模型的不同,这可以通过多种方式实现。
如果需要知道分支是否已合并到master中,那么如果mytopicbranch已合并,则以下命令将不会生成任何输出(即,可以删除它)。
1 | $ git rev-list master | grep $(git rev-parse myTopicBranch) |
。
您可以使用git branch命令解析bash中的所有分支,并对所有分支执行
Kuboon的回答没有删除分支名称中包含单词master的分支。他的回答有以下改进:
1 | git branch -r --merged | grep -v"origin/master$" | sed 's/\s*origin\///' | xargs -n 1 git push --delete origin |
号
当然,它不会删除"master"分支本身:)
下面是一篇帮助那些想要理解这些命令的人的文章:由史蒂文·哈曼撰写的git clean:delete already merged brancheds。
您可以使用
1 | git-del-br -a |
号
您可以使用
1 | pip install git-del-br |
P.S:我是这个工具的作者。欢迎提出任何建议/反馈。
亚当更新答案的别名版本:
1 2 | [alias] branch-cleanup ="!git branch --merged | egrep -v "(^\\*|master|dev)" | xargs git branch -d #" |
号
另外,有关如何转义复杂别名的简单提示,请参见此答案。
基于这些答案,我也编写了自己的bash脚本来完成它!
它使用
1 2 3 4 5 6 7 8 9 10 11 12 | 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 } |
号
如果您要删除所有已合并到当前所在分支的本地分支,那么根据前面的回答,我会想出一个安全的命令来执行此操作:
1 | git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d |
号
此命令不会影响当前分支或主分支。它还将使用xargs的-t标志,在执行之前告诉您它在做什么。
尝试以下命令:
git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))
号
使用
要对远程分支执行相同的操作(用远程名称更改
git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)
号
如果你有多个遥控器,在
如果上述命令失败,请先尝试删除合并的远程跟踪分支:
git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))
号
然后,
如果您经常使用它,可以考虑将其作为别名添加到您的
如果您错误地删除了一些分支,请使用
下面的查询对我有效
1 | 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连接上不太好。
我使用Git流式命名方案,因此这对我来说非常安全:
1 | git branch --merged | grep -e"^\s\+\(fix\|feature\)/" | xargs git branch -d |
。
它主要寻找以字符串
编写一个脚本,其中Git签出所有已合并到master的分支。
然后做
最后,删除合并的分支。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
号
在安装了Git-Bash的Windows上,Egrep-V将不工作
1 | git branch --merged | grep -E -v"(master|test|dev)" | xargs git branch -d |
。
其中
使用
截至2018.07
把这个加到你的
1 | sweep = !"f() { git branch --merged | egrep -v "(^\\*|master|dev)" || true | xargs git branch -d; }; f" |
。
现在您只需致电
接受的解决方案非常好,但有一个问题是它还删除尚未合并到远程的本地分支。
如果你看输出,你会看到
1 2 3 4 5 6 7 | $ 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) |
分支
但是您也可以看到单词
因此,可以将原始答案更改为(拆分为多行以缩短行长)
1 2 3 4 | git branch --merged master -v | \ grep "\\[gone\\]" | \ sed -e 's/^..//' -e 's/\S* .*//' | \ xargs git branch -d |
。
以保护尚未合并的分支。也不需要大师保护它,因为它有一个遥远的起源,并不会显示为消失。
为了避免意外地从master以外的任何分支运行该命令,我使用以下bash脚本。否则,从已合并的非主分支运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/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 |
号
1 2 | $ git config --global alias.cleanup '!git branch --merged origin/master | egrep -v"(^\*|master|staging|dev)" | xargs git branch -d' |
(为了可读性,分成多行)
调用"git cleanup"将删除已经合并到源站/master中的本地分支。它跳过master、staging和dev,因为我们不想在正常情况下删除它们。
把它分解,这就是它所做的:
- 这将创建一个名为"清理"的全局别名(跨所有回购)
- 此命令返回已合并到
origin/master 中的分支名称列表。
- 这将从已合并的分支列表中删除master、staging和dev分支。我们不想删除这些分支,因为它们不是功能。
- 这将为每个未合并的分支运行
git branch -d xxxxx 命令。这将逐个删除本地分支。
对于Windows,可以使用以下命令安装cygwin并删除所有远程分支:
1 | 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 | cleanup ="!git branch --merged master | grep -v '^*\\|master' | xargs -n 1 git branch -D" |
。
我使用
windoze友好的python脚本(因为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/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(' '): branch = branch.strip() if branch.strip(' *') != 'master': print(repo.git_command('branch', '-d', branch).strip()) |
。
https://gist.github.com/techtonik/b3f0d4b9a56dbacb3afc
假设我有一个名为上游的远程站点和一个源站(Github风格,我的fork是源站,上游是上游)。
我不想从上游删除任何主控形状、头或任何内容。我也不想删除开发分支,因为这是我们从中创建PRS的公共分支。
列出所有远程分支,按合并的分支筛选:
1 | git branch -r |
从该列表中删除包含我知道的分支名称中不想删除的单词的行:
1 | sed '/develop\|master\|HEAD\|upstream/d' |
。
从引用名称中删除远程名称(origin/somebranch变为somebranch):
1 | sed 's/.*\///' |
号
使用xargs调用一行程序:
1 | xargs git push --delete origin |
号
把它们放在一起,你会得到:
1 | git branch -r --merged | sed '/develop\|master\|HEAD\|upstream/d' | sed 's/.*\///' | xargs git push --delete origin |
号
这只会给我留下一些我曾经工作过但尚未合并的分支。然后你可以一个一个地移除它们,因为不应该太多。
查找不再需要的分支:
1 | git branch -ar |
号
假设您找到了要删除的Branch1、Branch2和Branch3:
1 | git push --delete origin branch1 branch2 branch3 |
号
来自
https://github.com/tj/git extras/blob/master/commands.md git删除合并的分支
如果您希望删除已合并的本地分支并删除它们的远程设备,这里是我喜欢的一行程序:
1 | git branch --merged | xargs -I_br -- sh -c 'git branch -d _br; git push origin --delete _br' |
号
我的bash脚本贡献大致基于mmrobin的答案。
它使用一些有用的参数来指定include和exclude,或者只检查/删除本地或远程分支,而不是同时检查和删除这两个分支。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #!/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... " 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 ' ') git push $remote $branches done fi if ["$local" == 1 ]; then # Remove local branches locals=$(echo"$local_branches" | sed 's/origin\///g' | tr -d ' ') if [ -z"$locals" ]; then echo"No branches removed." else git branch -d $(echo"$locals" | tr -d ' ') fi fi fi fi |
号
1 2 | for b in $(git branch -a | grep -v"\(master\|remotes\)"); do \ git branch -D $b; done && git fetch -p |
我一直在使用以下方法删除一个命令中合并的本地和远程分支。
我的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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 ' '` # Remove local branches git branch -d `git branch --merged | grep -v 'master$' | grep -v"$current_branch$" | sed 's/origin\///g' | tr -d ' '` else echo"No branches removed." fi fi } |
号
原始来源
这不会删除主分支,但会删除合并的本地和远程分支。一旦您在rc文件中有了这个文件,只需运行
Here is the way to delete git branch
号
1 | git branch -D BranchName |
号
如果您在Windows上,您可以使用Windows PowerShell和Out-GridView(遗憾的是,它现在已在PowerShell核心中)来创建一个不错的分支列表,并用鼠标选择要删除的分支:
1 | git branch --merged | Out-GridView -PassThru | % { git branch -d $_.Trim() } |
。单击"确定"后,PowerShell会将此分支名称传递给
如果使用分支模型(如hubflow或gitflow),则可以使用此命令删除合并的功能分支:
埃多克斯1〔9〕