如何修剪本地跟踪分支,这些分支在远程不存在了?

1322

使用git remote prune origin可以删除本地不再追踪的远程分支。

但是我也想删除从这些远程分支创建的本地分支(检查它们是否未合并会很好)。

我应该怎么做?


12
可能是「删除不在远程的本地分支」的重复问题。 - kolen
6
一句话介绍:跨平台的命令行工具,不会让人觉得像猫睡在你的键盘上一样混乱。要使用此工具,请先安装_node.js_。使用npx git-removed-branches(干运行) 或 npx git-removed-branches --prune(真实运行)。详细信息请参见以下答案 - Cristian Diaconescu
我通常认为这些事情应该是有意识地完成,而不是自动化的,否则你会面临删除你不想删除的东西的风险。因此,我会坚持使用 git branch -d localBranchName 和 git push origin --delete remoteBranchName。 - Epirocks
3
对于使用IntelliJ的用户,以下插件正好满足您的需求:https://plugins.jetbrains.com/plugin/10059-git-branch-cleaner - Daniel
40个回答

4
您可以通过以下简单的步骤来完成此操作:
  • 将所有分支输出到临时文件中:
git branch > branches.tmp
  • 打开文件并删除分支,以便将它们从本地中排除(例如develop/master/main/...等分支)
  • 通过cat命令将分支名称传递给xargs,然后删除这些分支:
cat branches.tmp | xargs git branch -D

4

不确定如何一次性完成所有操作,但是git git branch -d <分支名> 仅在分支完全合并时才会删除本地分支。请注意小写的 d。

git branch -D <分支名>(请注意大写的 D)将无论其是否已合并都会删除本地分支。


在Windows上,其他答案对我没有用。使用这个简单的-D开关的答案确实起作用了(即使分支已经被“删除”)。 - user4275029
我们能否一次性为所有分支完成这个操作? - Teoman shipahi

3

你实际上不需要过滤任何分支(例如主分支)。如果它被“合并”,那只意味着它将删除你的本地副本,但是“git checkout dev”将从远程创建一个本地分支(如果尚不存在)。 - csga5000
但即使它们已经被合并,本地分支列表仍然存在。此命令用于删除那些已从远程删除的分支。 - sendon1982
星号在开头表示当前分支,当您在不同的分支上运行该命令时可能会出现问题。 - OzzyCzech

3

Schleis的变体对我不起作用(Ubuntu 12.04),所以让我提出我自己的(清晰明了:))变体:

选项1(我更喜欢这个选项):

git for-each-ref --format='%(refname:short) %(upstream)' refs/heads/ | awk '$2 !~/^refs\/remotes/' | xargs git branch -D 

变体2:

a. 模拟运行:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | awk '{print "git branch -D " $1}'
b. 删除分支:
comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | xargs git branch -D

3
在Windows上使用Powershell,无论合并状态如何,要删除所有已在远程删除的本地分支,可以使用以下命令:
git fetch -p
git branch --v | ? {$_.contains('[gone]')} | % {$_.trim().split()[0].trim()} | % {git branch -D $_}
  • git branch --v 命令列出你的分支,其中关键信息包括 [gone] 状态
  • ? {$_.contains('[gone]')} 如果存在 [gone],返回 True
  • % {$_.trim().split()[0].trim()} 只显示分支名
  • % {git branch -D $_} 强制删除本地分支,即使未合并

如果要避免删除未合并的分支,请将选项 -D 改为 -d 并手动处理。


3

我使用 git 2.21.0,这个方法对我有效 - 它会删除本地跟踪分支,这些分支已经合并到 HEAD 中,并且之前曾在 push 时使用了 --set-upstream(我使用 push.default=upstream,因为它与多个远程仓库最兼容),而且那个上游分支已被 fetch --prune 删除(或者如果 git 配置中设置了 fetch.prune=true,则隐式删除):

git branch -vv --merged | grep ': gone]' | awk '{print $1}' | xargs git branch -d

使用--merged-d使得这是一个非常“安全”的删除操作。更加激进的版本可以省略--merged并使用-D

请注意,您必须检出跟踪现有远程分支的分支,否则在管道传输到xargs之前的命令将返回*而不是分支名称。我的建议是使用git checkout master; git branch -vv --merged | grep ': gone]' | awk '{print $1}' | xargs git branch -d - Tian

2

以下是git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d的Powershell版本:

git branch --merged master | %{ if($_ -notmatch '\*.*master'){ git branch -d "$($_.Trim())" }}

当你在主分支上时,这将删除已合并到主分支的任何本地分支。

使用git checkout master进行切换。


2
以下是对Windows用户的@wisbucky答案的改编: for /f "tokens=1" %i in ('git branch -vv ^| findstr ": gone]"') DO git branch %i -d 我使用posh-git,不幸的是,PowerShell不喜欢裸用的for,所以我创建了一个名为PruneOrphanBranches.cmd的普通命令脚本:
@ECHO OFF
for /f "tokens=1" %%i in ('git branch -vv ^| findstr ": gone]"') DO CALL :ProcessBranch %%i %1

GOTO :EOF

:ProcessBranch
IF /I "%2%"=="-d" (
    git branch %1 %2
) ELSE (
    CALL :OutputMessage %1
)
GOTO :EOF

:OutputMessage
ECHO Will delete branch [%1] 
GOTO :EOF

:EOF

不带参数调用可查看列表,使用“-d”参数执行实际删除操作,或使用“-D”参数删除所有未完全合并但仍想删除的分支。


这对我没用,不知何故,在findstr中的::(带空格)导致它每次都匹配所有内容 - 我差点删除了主分支。然而,使用正则表达式可以正常工作:git branch -vv ^| findstr /R " \[origin/[0-9]+: gone\] " - Josh

2

根据以上答案,我得出了这个一行代码的解决方案:

git remote prune origin; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

2

使用类似于@wisbucky答案中的变体,我将以下内容作为别名添加到了我的~/.gitconfig文件中:

pruneitgood = "!f() { \
    git remote prune origin; \
    git branch -vv | perl -nae 'system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}'; \
}; f"

通过这个命令 git pruneitgood ,可以清理掉那些在合并之后不再需要的本地和远程分支。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接