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

发布于 2024-11-10 03:24:14 字数 43 浏览 5 评论 0 原文

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

How do I delete branches which have already been merged? Can I delete them all at once, instead of deleting each branch one-by-one?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

岁月苍老的讽刺 2024-11-17 03:24:14

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


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

git branch --merged

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

git branch --merged | grep -Ev "(^\*|^\+|master|main|dev)"

第一部分 (^\*|^+) 排除当前分支和在另一个工作树中检出的任何分支。

如果想跳过,可以将其添加到egrep命令中,如下所示。分支 skip_branch_name 将不会被删除。

git branch --merged | grep -Ev "(^\*|^\+|master|main|dev|skip_branch_name)"

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

git branch --merged | grep -Ev "(^\*|^\+|master|main|dev)" | xargs --no-run-if-empty 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

NOTE: You can add other branches to exclude like master and dev if your workflow has those as a possible ancestor. Usually I branch off of a "sprint-start" tag and master, dev and qa are not ancestors.


First, list locally-tracking branches that were merged in remote (consider using -r flag to list all remote-tracking branches).

git branch --merged

You might see few branches you don't want to remove. We can add few arguments to skip important branches that we don't want to delete like master or a develop. The following command will skip master branch and anything that has dev in it.

git branch --merged | grep -Ev "(^\*|^\+|master|main|dev)"

The first part (^\*|^+) exclude the current branch and any branch checked out in another worktree.

If you want to skip, you can add it to the egrep command like the following. The branch skip_branch_name will not be deleted.

git branch --merged | grep -Ev "(^\*|^\+|master|main|dev|skip_branch_name)"

To delete all local branches that are already merged into the currently checked out branch:

git branch --merged | grep -Ev "(^\*|^\+|master|main|dev)" | xargs --no-run-if-empty git branch -d

You can see that master and dev are excluded in case they are an ancestor.


You can delete a merged local branch with:

git branch -d branchname

If it's not merged, use:

git branch -D branchname

To delete it from the remote use:

git push --delete origin branchname

git push origin :branchname    # for really old git

Once you delete the branch from the remote, you can prune to get rid of remote tracking branches with:

git remote prune origin

or prune individual remote tracking branches, as the other answer suggests, with:

git branch -dr branchname
凉城凉梦凉人心 2024-11-17 03:24:14

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

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 (by @oliver; 因为不适合评论,但已经有足够的答案):如果您在分支 ABC 上,则ABC 将出现在 gitbranch -r --merged 的结果中,因为未指定分支,因此分支默认为当前分支,并且分支始终符合合并到自身的条件(因为没有差异)分支与其自身之间!)。

因此,要么指定分支:

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

要么首先结账主控:

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

To delete all branches on remote that are already merged:

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

In more recent versions of Git

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

UPDATE (by @oliver; since does not fit in comment, but enough answers already): if you are on branch ABC then ABC will appear in the results of git branch -r --merged because the branch is not specified, so branch defaults to current branch, and a branch always qualifies as merged to itself (because there are no differences between a branch and itself!).

So either specify the branch:

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

OR first checkout master:

git checkout master | git branch -r --merged | grep -v ...
ま柒月 2024-11-17 03:24:14

只需稍微扩展 Adam 的答案:

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

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

,然后您可以删除所有本地合并分支,执行简单的 git cleanup代码>.

Just extending Adam's answer a little bit:

Add this to your Git configuration by running git config -e --global

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

And then you can delete all the local merged branches doing a simple git cleanup.

固执像三岁 2024-11-17 03:24:14

您需要排除 mastermainmaster 。从这些命令中开发分支。

本地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

You'll want to exclude the master, main & develop branches from those commands.

Local git clear:

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

Remote git clear:

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

Sync local registry of remote branches:

git fetch -p
北风几吹夏 2024-11-17 03:24:14

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

git branch --merged | grep -v '^* master

编辑:也忽略主分支,因为它现在正在使用

| grep -v '^ master

编辑:也忽略主分支,因为它现在正在使用

| grep -v '^* main

编辑:也忽略主分支,因为它现在正在使用

| grep -v '^ main

编辑:也忽略主分支,因为它现在正在使用

| xargs git branch -d

编辑:也忽略主分支,因为它现在正在使用

This also works to delete all merged branches except master.

git branch --merged | grep -v '^* master

Edit: Also ignoring main branch as it's being used these days

| grep -v '^ master

Edit: Also ignoring main branch as it's being used these days

| grep -v '^* main

Edit: Also ignoring main branch as it's being used these days

| grep -v '^ main

Edit: Also ignoring main branch as it's being used these days

| xargs git branch -d

Edit: Also ignoring main branch as it's being used these days

情魔剑神 2024-11-17 03:24:14

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

For those of you that are on Windows and prefer PowerShell scripts, here is one that deletes local merged branches:

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 $_ }
}

Or the short version:

git branch --merged | %{$_.trim()}  | ?{$_ -notmatch 'dev' -and $_ -notmatch 'master' -and $_ -notmatch 'main'} | %{git branch -d $_.trim()}
何以畏孤独 2024-11-17 03:24:14

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

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

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

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

TL;DR

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

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 存储库是最简单的分支和提交来测试正确的行为:

使用单个提交创建一个新的 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

<前><代码>栏
发展

* 掌握
高超的
不是大师

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

原始正则表达式缺少分支“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 标志。默认行为是仅删除已合并到 master 的分支,但 -f 标志将删除已合并到当前分支的分支。

git sweep
已删除分支栏(为 9a56952)。
删除了 masterful 分支(为 9a56952)。
删除分支 notmaster (为 9a56952)。
git sweep -f
已删除分支 foo(原为 2cea1ab)。

I've used Adam's answer for years now. That said, that there are some cases where it wasn't behaving as I expected:

  1. branches that contained the word "master" were ignored, e.g. "notmaster" or "masterful", rather than only the master branch
  2. branches that contained the word "dev" were ignored, e.g. "dev-test", rather than only the dev branch
  3. deleting branches that are reachable from the HEAD of the current branch (that is, not necessarily master)
  4. in detached HEAD state, deleting every branch reachable from the current commit

1 & 2 were straightforward to address, with just a change to the regex.
3 depends on the context of what you want (i.e. only delete branches that haven't been merged into master or against your current branch).
4 has the potential to be disastrous (although recoverable with git reflog), if you unintentionally ran this in detached HEAD state.

Finally, I wanted this to all be in a one-liner that didn't require a separate (Bash|Ruby|Python) script.

TL;DR

Create a git alias "sweep" that accepts an optional -f flag:

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

and invoke it with:

git sweep

or:

git sweep -f

The long, detailed answer

It was easiest for me to create an example git repo with some branches and commits to test the correct behavior:

Create a new git repo with a single commit

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

Create some new branches

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

Desired behavior: select all merged branches except: master, develop or current

The original regex misses the branches "masterful" and "notmaster" :

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

With the updated regex (which now excludes "develop" rather than "dev"):

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

Switch to branch foo, make a new commit, then checkout a new branch, foobar, based on foo:

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

My current branch is foobar, and if I re-run the above command to list the branches I want to delete, the branch "foo" is included even though it hasn't been merged into master:

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

However, if I run the same command on master, the branch "foo" is not included:

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

And this is simply because git branch --merged defaults to the HEAD of the current branch if not otherwise specified. At least for my workflow, I don't want to delete local branches unless they've been merged to master, so I prefer the following variant using git rev-parse:

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

Detached HEAD state

Relying on the default behavior of git branch --merged has even more significant consequences in detached HEAD state:

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

This would have deleted the branch I was just on, "foobar" along with "foo", which is almost certainly not the desired outcome.
With our revised command, however:

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

One line, including the actual delete

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

All wrapped up into a git alias "sweep":

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

The alias accepts an optional -f flag. The default behavior is to only delete branches that have been merged into master, but the -f flag will delete branches that have been merged into the current branch.

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).
红墙和绿瓦 2024-11-17 03:24:14

这里有很多不好的答案。这可能是您想要的:

git branch --delete $(git branch --merged master --no-contains master --format='%(refname:short)')

这会选择已合并到 master 中的所有本地分支(包括 master)、 非后代分支master(不包括 master 本身)。 --format 是必需的,因为默认情况下 Git 会为当前签出的分支打印星号。您也可以使用 git for-each-ref 来完成此操作,但它似乎更复杂(它也列出了远程分支)。

想要:

  • gitbranch--merged(没有master):这将列出已“合并”到您的< em>当前已签出提交(即HEAD),这可能是意外的并且不是您想要的。
  • <代码>| grep -v master:没有必要这样做;你可以只使用--no-contains
  • <代码>| xargs:再次强调,不需要。 gitbranch --delete 可以删除多个分支。

更新:我已经使用这个有一段时间了,效果很好。有两个小缺陷:

  1. 如果没有要删除的分支,则会出现错误。在我看来,这对于交互式使用来说很好。无论如何,您都不应该在脚本中使用它,因为它是 Bash,并且 Bash 不应该用于脚本编写

  2. 它不会删除指向与 master 相同提交的分支。我有一个工具,它可以自动对我的所有分支进行变基,对于已合并的分支,它可以将它们保留在其中这种状态。这对你来说可能并不重要。

So many bad answers here. This is what you probably want:

git branch --delete $(git branch --merged master --no-contains master --format='%(refname:short)')

This selects all local branches that have been merged into master (including master), and that aren't descendent of master (which excludes master itself). The --format is necessary because by default Git prints asterisks for the currently checked out branches. You might be able to do this with git for-each-ref too but it seems more complicated (it lists remote branches too).

You don't want:

  • git branch --merged (without master): This will list branches that have been "merged" into your currently checked out commit (i.e. HEAD), which is probably unexpected and not what you want.
  • | grep -v master: There's no need for this; you can just use --no-contains.
  • | xargs: Again, no need. git branch --delete can delete more than one branch.

Update: I've been using this for a while and it works pretty well. There are two minor flaws:

  1. If there are no branches to delete it will give you an error. That's fine for interactive use IMO. You shouldn't be using this in a script anyway since it's Bash and Bash should not be used for scripting.

  2. It won't delete branches that point to the same commit as master. I have a tool that automatically rebases all my branches, and for ones that have been merged it can leave them in this state. This may not matter to you.

盗心人 2024-11-17 03:24:14

使用 Git 版本 2.5.0:

git branch -d `git branch --merged`

Using Git version 2.5.0:

git branch -d `git branch --merged`
薄荷港 2024-11-17 03:24:14

如果您使用的是 Windows,则可以通过 Out-GridView 以获得一个不错的分支列表,并用鼠标选择要删除的分支:

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

在此处输入图像描述
单击“确定”后,Powershell 会将此分支名称传递给 gitbranch -d 命令并删除它们
输入图像描述这里

If you're on Windows you can use Windows Powershell or Powershell 7 with Out-GridView to have a nice list of branches and select with mouse which one you want to delete:

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

enter image description here
after clicking OK Powershell will pass this branches names to git branch -d command and delete them
enter image description here

赢得她心 2024-11-17 03:24:14

您可以将提交添加到 --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 替换为 echo

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

You can add the commit to the --merged option.
This way you can make sure only to remove branches which are merged into i.e. the origin/master

Following command will remove merged branches from your origin.

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

You can test which branches will be removed replacing the git push origin --delete with echo

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
唐婉 2024-11-17 03:24:14

我最喜欢的简单脚本:

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

My favorite and simple script:

git branch --merged | grep -E -v "(master|main|develop|other)" | xargs git branch -d
相对绾红妆 2024-11-17 03:24:14

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

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

如果您想排除 ma​​ster 或任何其他分支名称,您可以像这样使用 PowerShell Select-String 进行管道传输,并将结果传递给 gitbranch -d< /代码>:

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

How to delete merged branches in PowerShell console

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

If you want to exclude master or any other branch names, you can pipe with PowerShell Select-String like this and pass the result to git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})
深府石板幽径 2024-11-17 03:24:14

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

I use the following Ruby script to delete my already merged local and remote branches. If I'm doing it for a repository with multiple remotes and only want to delete from one, I just add a select statement to the remotes list to only get the remotes I want.

#!/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
饮惑 2024-11-17 03:24:14

注意:我对以前的答案不满意(不适用于所有系统,不适用于远程,未指定 --merged 分支,未精确过滤)。所以,我添加我自己的答案。

主要有两种情况:

本地

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

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

注意

  • gitbranchoutput--format“..”是去掉空格,允许精确的 grep 匹配
  • grep -E 使用而不是 egrep,因此它也可以在没有egrep 的系统中工作(即:Windows 的 git)。
  • grep -E -v '^master$|^feature/develop$' 是指定我不想删除的本地分支
  • xargs -n 1 gitbranch -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

注意

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

注意

  • gitbranchoutput--format“..”是去掉空格,允许精确的 grep 匹配
  • grep -E 使用而不是 egrep,因此它也可以在没有egrep 的系统中工作(即:Windows 的 git)。
  • grep -E -v '^master$|^feature/develop$' 是指定我不想删除的本地分支
  • xargs -n 1 gitbranch -d >:执行本地分支的删除(这对远程分支不起作用)
  • 当然如果您尝试删除当前签出的分支,您会收到错误。所以,我建议提前切换到master。

远程

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


注意

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

Note: I am not happy with previous answers, (not working on all systems, not working on remote, not specifying the --merged branch, not filtering exactly). So, I add my own answer.

There are two main cases:

Local

You want to delete local branches that are already merged to another local branch. During the deletion, you want to keep some important branches, like master, develop, etc.

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

Notes:

  • git branch output --format ".." is to strip whitespaces and allow exact grep matching
  • grep -E is used instead of egrep, so it works also in systems without egrep (i.e.: git for windows).
  • grep -E -v '^master$|^feature/develop$' is to specify local branches that I don't want to delete
  • xargs -n 1 git branch -d: perform the deletion of local branches (it won't work for remote ones)
  • of course you get an error if you try deleting the branch currently checked-out. So, I suggest to switch to master beforehand.

Remote

You want to delete remote branches that are already merged to another remote branch. During the deletion, you want to keep some important branches, like HEAD, master, releases, etc.

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

Notes:

  • for remote, we use the -r option and provide the full branch name: origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' is to match the remote branches that we don't want to delete.
  • cut -d/ -f2- : remove the unneeded 'origin/' prefix that otherwise is printed out by the git branch command.
  • xargs -n 1 git push --delete origin : perform the deletion of remote branches.
| xargs -n 1 git branch -d

Notes:

  • git branch output --format ".." is to strip whitespaces and allow exact grep matching
  • grep -E is used instead of egrep, so it works also in systems without egrep (i.e.: git for windows).
  • grep -E -v '^master$|^feature/develop$' is to specify local branches that I don't want to delete
  • xargs -n 1 git branch -d: perform the deletion of local branches (it won't work for remote ones)
  • of course you get an error if you try deleting the branch currently checked-out. So, I suggest to switch to master beforehand.

Remote

You want to delete remote branches that are already merged to another remote branch. During the deletion, you want to keep some important branches, like HEAD, master, releases, etc.


Notes:

  • for remote, we use the -r option and provide the full branch name: origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' is to match the remote branches that we don't want to delete.
  • cut -d/ -f2- : remove the unneeded 'origin/' prefix that otherwise is printed out by the git branch command.
  • xargs -n 1 git push --delete origin : perform the deletion of remote branches.
夜唯美灬不弃 2024-11-17 03:24:14

我使用这个:

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

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

I use this:

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

It lists all merged branched in the specified format, then it feeds that list to git branch --delete.

丶视觉 2024-11-17 03:24:14

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

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

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

kuboon's answer missed deleting branches which have the word master in the branch name.
The following improves on his answer:

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

Of course, it does not delete the "master" branch itself :)

眼眸 2024-11-17 03:24:14

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

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

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

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

There is no command in Git that will do this for you automatically. But you can write a script that uses Git commands to give you what you need. This could be done in many ways depending on what branching model you are using.

If you need to know if a branch has been merged into master the following command will yield no output if myTopicBranch has been merged (i.e. you can delete it)

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

You could use the Git branch command and parse out all branches in Bash and do a for loop over all branches. In this loop you check with above command if you can delete the branch or not.

时光暖心i 2024-11-17 03:24:14

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

对于那些希望了解这些命令的人来说,这是一篇有用的文章: Git Clean:删除已合并的分支,作者:史蒂文·哈曼

git branch --merged | grep -Ev '^(. master|\*)' | xargs -n 1 git branch -d will delete all local branches except the current checked out branch and/or master.

Here's a helpful article for those looking to understand these commands: Git Clean: Delete Already Merged Branches, by Steven Harman.

‘画卷フ 2024-11-17 03:24:14

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

git-del-br -a

您可以使用 pip 安装它

pip install git-del-br

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

You can use git-del-br tool.

git-del-br -a

You can install it via pip using

pip install git-del-br

P.S: I am the author of the tool. Any suggestions/feedback are welcome.

遗心遗梦遗幸福 2024-11-17 03:24:14

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

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

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

I use a git-flow esque naming scheme, so this works very safely for me:

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

It basically looks for merged commits that start with either string fix/ or feature/.

怪我鬧 2024-11-17 03:24:14

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

如果您查看输出,您会看到类似

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

Branches blaissue_248 的内容是本地分支,它们将被静默删除。

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

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

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

以保护尚未合并的分支。
此外,不需要对 master 进行 grep 保护以保护它,因为它在原点有一个遥控器,并且不会显示为已消失。

The accepted solution is pretty good, but has the one issue that it also deletes local branches that were not yet merged into a remote.

If you look at the output of you will see something like

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

Branches bla and issue_248 are local branches that would be deleted silently.

But you can also see the word [gone], which indicate branches that had been pushed to a remote (which is now gone) and thus denote branches can be deleted.

The original answer can thus be changed to (split into multiline for shorter line length)

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

to protect the not yet merged branches.
Also the grepping for master to protect it, is not needed, as this has a remote at origin and does not show up as gone.

怼怹恏 2024-11-17 03:24:14

在安装了 git bash 的 Windows 上 egrep -v 将无法使用

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

grep - E -v 相当于 egrep -v

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

On Windows with git bash installed egrep -v will not work

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

where grep -E -v is equivalent of egrep -v

Use -d to remove already merged branches or
-D to remove unmerged branches

对风讲故事 2024-11-17 03:24:14

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

git branch --merged | grep -v \* | grep -v '^\s*master

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

| xargs -t -n 1 git branch -d

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

If you'd like to delete all local branches that are already merged in to the branch that you are currently on, then I've come up with a safe command to do so, based on earlier answers:

git branch --merged | grep -v \* | grep -v '^\s*master

This command will not affect your current branch or your master branch. It will also tell you what it's doing before it does it, using the -t flag of xargs.

| xargs -t -n 1 git branch -d

This command will not affect your current branch or your master branch. It will also tell you what it's doing before it does it, using the -t flag of xargs.

表情可笑 2024-11-17 03:24:14

Adam 的更新答案的别名版本:

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

另请参阅这个答案提供了有关转义复杂别名的便捷提示。

Alias version of Adam's updated answer:

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

Also, see this answer for handy tips on escaping complex aliases.

放我走吧 2024-11-17 03:24:14

下面的查询对我有用

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 连接上效果不太好。

Below query works for me

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

and this will filter any given branch in the grep pipe.

Works well over http clone, but not so well for the ssh connection.

守护在此方 2024-11-17 03:24:14

基于其中一些答案,我制作了我自己的 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
}

Based on some of these answers I made my own Bash script to do it too!

It uses git branch --merged and git branch -d to delete the branches that have been merged and prompts you for each of the branches before deleting.

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
}
指尖微凉心微凉 2024-11-17 03:24:14

尝试以下命令:

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)

如果您有多个远程分支,请在 之前添加 grep origin | >cut 仅过滤origin

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

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

然后 git fetch再次远程并再次使用之前的 git push -vd 命令。

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

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

Try the following command:

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

By using git rev-parse will get the current branch name in order to exclude it. If you got the error, that means there are no local branches to remove.

To do the same with remote branches (change origin with your remote name), try:

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

In case you've multiple remotes, add grep origin | before cut to filter only the origin.

If above command fails, try to delete the merged remote-tracking branches first:

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

Then git fetch the remote again and use the previous git push -vdcommand again.

If you're using it often, consider adding as aliases into your ~/.gitconfig file.

In case you've removed some branches by mistake, use git reflog to find the lost commits.

浅紫色的梦幻 2024-11-17 03:24:14

从 2018.07 开始,

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

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

现在您只需调用 git swing 即可执行所需的清理。

As of 2018.07

Add this to [alias] section of your ~/.gitconfig:

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

Now you can just call git sweep to perform that needed cleanup.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文