【问题标题】:Remove tracking branches no longer on remote不再远程删除跟踪分支
【发布时间】:2011-12-05 07:57:28
【问题描述】:

是否有一种简单的方法可以删除远程等效不再存在的所有跟踪分支?

例子:

分支(本地和远程)

  • 主人
  • 起源/主人
  • 起源/错误修复-a
  • 起源/错误修复-b
  • 起源/错误修复-c

在本地,我只有一个 master 分支。现在我需要处理bug-fix-a,所以我检查它,处理它,并将更改推送到远程。接下来我对 bug-fix-b 做同样的事情。

分支(本地和远程)

  • 主人
  • 错误修复-a
  • 错误修复-b
  • 起源/主人
  • 起源/错误修复-a
  • 起源/错误修复-b
  • 起源/错误修复-c

现在我有本地分支 masterbug-fix-abug-fix-b。 Master 分支维护者会将我的更改合并到 master 并删除他已经合并的所有分支。

所以现在的状态是:

分支(本地和远程)

  • 主人
  • 错误修复-a
  • 错误修复-b
  • 起源/主人
  • 起源/错误修复-c

现在我想调用一些命令来删除不再代表的分支(在本例中为 bug-fix-abug-fix-b)在远程存储库中。

它类似于现有的命令git remote prune origin,但更像git local prune origin

【问题讨论】:

  • 措辞出色的问题,带有非常清晰的示例。干得好!
  • 为什么大多数答案回答:“删除已合并的分支”,当问题专门针对“不再远程的分支”时。这是一个很大的区别。

标签: git git-branch


【解决方案1】:

git remote prune origin 修剪不在远程的跟踪分支。

git branch --merged 列出已合并到当前分支的分支。

xargs git branch -d 删除标准输入中列出的分支。

小心删除git branch --merged 列出的分支。该列表可能包括 master 或您不想删除的其他分支。

为了让自己有机会在删除分支之前编辑列表,您可以在一行中执行以下操作:

git branch --merged >/tmp/merged-branches && \
  vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

【讨论】:

  • 合并分支的第一行在我的系统上是* master。以下命令对我有用:git branch -d $(git branch --merged |tail -n +2)
  • 如果我在develop 上,那么git branch --merged 包括master!您可能(绝对!)不想删除它。另外我认为应该是git branch -d,其中小写-d 表示“安全删除”,例如仅在合并后删除。
  • 似乎提供了改进的解决方案there
  • 删除合并很有用,但与“删除不在远程的分支”不同。
  • 只用grep排除master:git branch --merged | grep -v "master" &gt;/tmp/merged-branches &amp;&amp; vi /tmp/merged-branches &amp;&amp; xargs git branch -d &lt;/tmp/merged-branches
【解决方案2】:

命令后

git fetch -p

在您运行时删除远程引用

git branch -vv

它将显示“已离开”作为远程状态。例如,

$ git branch -vv
  master                 b900de9 [origin/master: behind 4] Fixed bug
  release/v3.8           fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
  release/v3.9           0d680d0 [origin/release/v3.9: behind 2] Updated comments
  bug/1234               57379e4 [origin/bug/1234: gone] Fixed bug

所以你可以编写一个简单的脚本来删除已经远程的本地分支:

git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done

注意以上使用“瓷器”命令git branch获取上游状态。

获得此状态的另一种方法是使用“管道”命令git for-each-ref 和插值变量%(upstream:track),就像上面一样,它将是[gone]

这种方法更安全一些,因为不存在意外匹配部分提交消息的风险。

git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}'); do git branch -D $branch; done

【讨论】:

  • @KrzysztofWende - 不在 Solaris 和一些 BSD 和一些 OS X 上:)
  • 看起来这也会删除在最后一个提交消息中“消失”的任何分支。
  • @dlsso 如果最后的提交消息包含字符串 ":gone]" 那么是的,它也会被删除。您可以通过额外的 awk/gawk 来剥离提交消息,以牺牲简单性为代价使其更健壮。 git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
  • 在回复我之前的评论(问题)时,当前分支有 * 作为第一个字段。如果它恰好也在“已消失”分支列表中,则 $1 将被分配 * 并将被解释为带有 awk 吐出文件和文件夹名称的文件规范。我消除了 grep 表达式并让 awk 完成所有过滤:awk '/: gone]/{if ($1!="*") print $1}'。现在可以按预期工作了。
  • @ahmedbhs 因为该命令使用单引号 ' 你需要使用双引号 " 来包围整个命令。此外,作为 shell 命令的 git 别名(如这个)需要 ! 在开头。这为我工作:test = "!git fetch -p &amp;&amp; for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
【解决方案3】:

这些答案中的大多数实际上并未回答原始问题。我做了一堆挖掘工作,this 是我找到的最干净的解决方案。这是该答案的稍微更彻底的版本:

  1. 检查您的默认分支。通常git checkout master
  2. 运行git fetch -p &amp;&amp; git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

说明:

通过修剪您的跟踪分支然后删除在git branch -vv 中显示它们“已消失”的本地分支来工作。

注意事项:

如果您的语言设置为英语以外的其他语言,您需要将gone 更改为适当的单词。仅本地的分支不会被触及。已在远程删除但未合并的分支将显示通知但不会在本地删除。如果您也想删除这些,请将-d 更改为-D

【讨论】:

  • 应该在 git branch 之前添加 LANG=en_US 以强制英语: git fetch --prune && LANG=en_US git branch -vv | awk '/: 消失了]/{print $1}' | xargs git 分支 -d
  • 我会在命令的开头添加git checkout master &amp;&amp; ...
  • 当你在一个应该被删除的分支上时,这是很危险的——在这种情况下,第一列是'*',然后传递给 xargs。为了改善这一点,在将输出传递给 awk 之前添加剥离 '*' 字符: sed -e 's/^*//'
  • @dlsso 这些说明适用于大多数人,但并不适用于所有人(请参阅上面的评论)。说人们应该从意外删除的分支中学习(他们可能不容易知道如何恢复)是光顾,当您可以使说明更安全时。你,你自己在上面写道“那个确切的建议是不安全的”。我仍然认为安全比总是工作更重要。人们最好从“不工作”中学习,而不是从已删除的分支中学习。
  • 小心!有一个极端情况会导致删除所有本地分支:如果您当前位于远程删除的分支上,git branch -vv 的输出将以星号开头,最终将导致执行git branch -d *。这是一个补丁版本,它将忽略带星号的行:git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
【解决方案4】:

我通常不会回答已经有 16 个答案的问题,但其他所有答案都是错误的,而正确答案就是这么简单。问题是:“有没有一种简单的方法可以删除所有远程等效不再存在的跟踪分支?”

如果“简单”意味着一次性删除它们,不脆弱,不危险,并且不依赖并非所有读者都会拥有的工具,那么正确答案是:不。

有些答案很简单,但它们并没有按照所要求的去做。其他人按照要求做,但并不简单:都依赖于通过文本操作命令或脚本语言解析 Git 输出,这可能不是每个系统都存在。最重要的是,大多数建议使用瓷器命令,其输出并非旨在由脚本解析(“瓷器”是指旨在用于人类操作的命令;脚本应使用较低级别的“管道”命令)。

延伸阅读:


如果您想安全地执行此操作,对于问题中的用例(垃圾收集跟踪已在服务器上删除但仍作为本地分支存在的分支)并且仅使用高级 Git 命令,您必须

  • git fetch --prune(或git fetch -p,它是一个别名,或者git prune remote origin,它在不获取的情况下做同样的事情,而且可能不是你大多数时候想要的)。
  • 注意所有报告为已删除的远程分支。或者,为了稍后找到它们,git branch -v(任何孤立的跟踪分支都将被标记为“[gone]”)。
  • git branch -d [branch_name] 在每个孤立的跟踪分支上

(这是其他一些答案所建议的)。

如果你想编写一个解决方案的脚本,那么for-each-ref 是你的起点,就像这里的Mark Longair's answerthis answer to another question,但是如果不编写shell 脚本循环,我看不到利用它的方法,或者使用 xargs 什么的。


背景说明

要了解发生了什么,您需要了解,在跟踪分支的情况下,您拥有的不是一个分支,而是三个。 (请记住,“分支”只是指向提交的指针。)

给定一个跟踪分支feature/X,远程存储库(服务器)将拥有这个分支并将其命名为feature/X。您的本地存储库有一个分支remotes/origin/feature/X,这意味着,“这是远程告诉我它的功能/X 分支,上次我们谈过的”,最后,本地存储库有一个分支feature/X,它指向您最新的提交,并配置为“跟踪”remotes/origin/feature/X,这意味着您可以拉和推以保持它们对齐。

在某个时候,有人删除了遥控器上的feature/X。从那一刻起,您就剩下本地的feature/X(您可能不再需要它,因为功能 X 的工作可能已经完成),以及您的 remotes/origin/feature/X,它肯定没用,因为它的唯一目的是记住服务器分支的状态。

Git 会让你自动清理多余的remotes/origin/feature/X——这就是git fetch --prune 所做的——但由于某种原因,它不会让你自动删除你自己的feature/X...即使你的feature/X 仍然包含孤立的跟踪信息,因此它具有识别已完全合并的前跟踪分支的信息。 (毕竟,它可以为提供让您自己手动操作的信息。)

【讨论】:

  • 这是一个更安全的答案。此外,与所选答案不同,如果您使用“Squash and Merge”工作流程,它将起作用。
  • 这实际上只回答了问题“如何找到消失的分支”的简单部分(以及使用 jason.rickman 在 2015 年发布的相同命令),然后告诉您删除所有手动分支,这正是 OP 不想做的事情。
  • @Voo 这就是答案的重点:不是告诉你怎么做(这只是一个奖励),而是告诉你答案是没有简单、简单的方法来做到这一点.这是问题的正确答案。
  • @Andrew 如果您有一个完全符合您要求的瓷器命令,那么您无法使用管道命令可靠地获得相同的输出,这似乎不太可能。我确实问过这个问题,不到一个小时就收到了an answer。可能应该按照这些思路发布答案(#17?)。
  • @user2864740 一些读者可能会认为编写一个小的 bash 脚本属于他们对“简单”的定义,这是一个完全可以辩护的立场,但我在第 2 段中给出了自己对“简单”的解释其余的答案与它一致。为了捍卫我公认的限制性解释,并非所有 Git 用户都有 xargs 或 bash,他们可能不是在这里寻找微编码挑战,而是他们可以安全地应用的快速答案,而不会进一步分散自己的注意力他们真正的目标。
【解决方案5】:

Windows 解决方案

对于 Microsoft Windows Powershell:

git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}

说明

git checkout master 切换到 master 分支

git remote update origin --prune 修剪远程分支

git branch -vv 获取所有分支的详细输出 (git reference)

Select-String -Pattern ": gone]" 仅获取已从远程删除的记录。

% { $_.toString().Trim().Split(" ")[0]}获取分支名称

% {git branch -d $_}删除分支

【讨论】:

  • 感谢您,尽管我必须在 .toString() 之后添加一个 .Trim() 才能删除分支名称前的两个空格。
  • 感谢这个命令。我必须将 git branch -d 更改为 git branch -D 否则我收到错误分支未完全合并。
  • @markieo 您可能已经知道这一点,但对其他人来说 - git branch -D 具有破坏性,并且会删除您尚未推送的本地工作。 -d 总是安全的,请小心 -D
【解决方案6】:

我在这里找到了答案: How can I delete all git branches which have been merged?

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

确保我们保持大师地位

您可以通过在第一个之后添加另一个grep 来确保master 或任何其他分支不会被删除。在这种情况下,你会去:

git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d

例如,如果我们想保留masterdevelopstaging,我们会:

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

将此设为别名

由于它有点长,您可能需要为您的.zshrc.bashrc 添加一个别名。我的叫gbpurge(代表git branches purge):

alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'

然后重新加载您的.bashrc.zshrc

. ~/.bashrc


. ~/.zshrc

【讨论】:

  • 有用,但与“删除不在远程的分支”不同
  • 很好的答案@karlingen,我在我的所有开发环境中都将其永久保存为 gbpurge
【解决方案7】:

在大多数其他解决方案中,“gone”的模式匹配对我来说有点吓人。为了更安全,这里使用--format 标志拉出每个分支的upstream tracking status

我需要一个 Windows 友好的版本,所以这会删除所有使用 Powershell 列为“已消失”的分支:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }

第一行列出了上游分支“已消失”的本地分支的名称。下一行删除空行(这是未“消失”的分支的输出),然后将分支名称传递给删除分支的命令。

【讨论】:

  • --format 选项似乎相当新;我需要将 git 从 2.10.something 升级到 2.16.3 才能获得它。这是我对 Linux 系统的修改:git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
  • 这是迄今为止最好的解决方案。一种建议是使用refname:short。然后你可以删除% { $_ -replace '^refs/heads/', '' }这一行
  • 这是一个很好的 windows 解决方案。我这样使用它是因为它更具可读性git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ } 也可能是使用-d 而不是-D 的好主意。不再远程的分支不需要强制删除。
  • 虽然对我们中的一些人来说显而易见,但可能值得一提的是,您应该首先运行“git remote update origin --prune”。
【解决方案8】:

删除所有已合并到master的分支,但不要尝试删除master本身:

git checkout master &amp;&amp; git pull origin master &amp;&amp; git fetch -p &amp;&amp; git branch -d $(git branch --merged | grep master -v)

或添加别名:

alias gitcleanlocal="git checkout master &amp;&amp; git pull origin master &amp;&amp; git fetch -p &amp;&amp; git branch -d $(git branch --merged | grep master -v)"

解释:

git checkout master结帐主分支

git pull origin master确保本地分支已合并所有远程更改

git fetch -p删除对已删除的远程分支的引用

git branch -d $(git branch master --merged | grep master -v)删除所有已经合并到master的分支,但不要尝试自己删除master

【讨论】:

  • 请注意,这非常有用,但它也会删除那些从未推送到远程的分支。只列出差异然后将您真正要删除的内容复制到git branch -D 命令中会更安全
  • 澄清一下,Zefiryn 指的是使用 -D 选项,它不是单行的一部分。
  • 或者使用小写的git branch -d 应该会发出关于未推送分支的警告。
【解决方案9】:

你可以这样做:

git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d

附: 正如Sam H.所指出的那样

先执行这个:

git remote prune origin

【讨论】:

  • 您不必先运行git remote prune origin 吗?
  • 如果你想强制删除,也传递xargs git branch -D(大写D)
【解决方案10】:

TL;DR:

移除所有不在远程的本地分支

git fetch -p && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D

删除所有不在远程 AND 上的本地分支,它们已完全合并且未使用,如之前许多答案中所述。

git fetch -p && git branch --merged | grep -v '*' | grep -v 'master' | xargs git branch -d

说明

  • git fetch -p 将修剪所有远程不再存在的分支
  • git branch -vv 将打印本地分支,修剪后的分支将标记为 gone
  • grep ': gone]' 只选择消失的分支
  • awk '{print $1}' 过滤输出以仅显示分支的名称
  • xargs git branch -D 将遍历所有行(分支)并强制删除此分支

为什么是git branch -D 而不是git branch -d,否则您将拥有未完全合并的分支。

error: The branch 'xxx' is not fully merged.

【讨论】:

  • 您是要说远程而不是主控吗?
【解决方案11】:
git fetch -p

这将修剪远程不再存在的任何分支。

【讨论】:

  • 这会删除远程引用,但不会删除本地分支本身。虽然是一个有用的命令,但我认为这不能回答 OP 的问题。
  • 什么?这会为我删除本地分支。
  • @AlexHall 远程仓库有一个分支X;你git checkout X;现在您的存储库有一个(本地)跟踪分支X 和一个远程分支origin/X;远程仓库删除X;你git fetch-p;在您的本地存储库中,不仅origin/X,而且X 已被删除。你说的是这个吗?
【解决方案12】:

又一个答案,因为没有一个解决方案适合我对优雅和跨平台的需求:

删除不在远程的本地分支的命令:

for b in $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads); do git branch -d $b; done

将其与 gitconfig 集成以便可以使用 git branch-prune 运行:

重击

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format='\''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'\'' refs/heads); do git branch -d $b; done'

PowerShell

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format=''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'' refs/heads); do git branch -d $b; done'

(需要帮助找到适用于 PowerShell 和 bash 的通用命令)

为什么这个答案是最好的?

  • 提供完整的解决方案:将git branch-prune 命令添加到您的 git 中
  • 在 Windows PowerShell 中运行良好
  • 核心思想是@jason.rickmanbulletproof method使用git for-each-ref
  • 使用--filter 完成解析和过滤,因此不需要外部依赖项

解释:

  • 为您的~\.gitconfig 添加一个新别名。执行此操作后,您可以简单地执行git branch-prune
  • 在此别名中:
    • 使用--prune 标志获取分支,该标志“修剪远程跟踪分支不再位于远程”
    • 使用git for-each-ref--filter,获取分支列表[gone](无远程)
    • 遍历此列表并安全删除分支

【讨论】:

  • 感谢 @jerry-wu 将这个解决方案的性能提升到无穷大。
  • @jerry-wu 并且您上次编辑的 git config 命令在 PowerShell 中不起作用((
  • 这是否也会删除尚未推送到远程的本地分支? (又名正在进行的工作)
  • 简短的回答是否定的。如果一个分支没有被合并,这里使用的git branch -d branch-name 命令不会删除它。它将发送一个分支未合并的通知,并显示删除它的命令(即git branch -D branch-name
  • 对我来说,这确实会报告分支未合并的错误,即使分支确实已完全合并并在合并后从远程删除。错误:分支 'feature/...' 未完全合并。 - 有什么建议吗?
【解决方案13】:

另一个答案,大量来自Patrick's answer(我喜欢它,因为它似乎消除了gone]git branch输出中匹配位置的任何歧义),但添加了一个*nix弯曲。

最简单的形式:

git branch --list --format \
  "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" \
  | xargs git branch -D

我已将其封装在路径上的 git-gone 脚本中:

#!/usr/bin/env bash

action() {
  ${DELETE} && xargs git branch -D || cat
}

get_gone() {
  git branch --list --format \
    "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)"
}

main() {
  DELETE=false
  while [ $# -gt 0 ] ; do
    case "${1}" in
      (-[dD] | --delete) DELETE=true ;;
    esac
    shift
  done
  get_gone | action
}

main "${@}"

NB - --format 选项似乎相当新;我需要将 git 从 2.10.something 升级到 2.16.3 才能获得它。

编辑:经过调整以包含来自 Benjamin W.

的关于 refname:short 的建议

NB2 - 我只在 bash 中测试过,因此是 hashbang,但可能可移植到 sh

【讨论】:

  • 您不能在第一行使用%(refname:short) 跳过sed 部分吗?
  • 似乎对我有用,我现在把它作为一个整洁的 Git 别名 - 这里是所有这些中最干净的解决方案!
  • 2.13 引入了--format。跳过sed 部分的另一种方法是使用git update-ref -d。请注意,这可能有点不安全,在这里使用git for-each-ref 更安全(给定--shell)。
  • 很好的答案,它帮助我在与--format 纠结于自己做这件事时回答了我自己的问题。只有一个问题:为什么是#!bash?对我来说,这里的所有东西都像便携的sh
  • 这只是我的正常样板,并没有在其他地方测试过。
【解决方案14】:

这将删除所有合并的本地分支,除了本地主引用和当前正在使用的分支:

git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d

这将删除所有已从“origin”引用的远程存储库中删除的分支,但仍然在“remotes/origin”中本地可用。

git remote prune origin

【讨论】:

  • git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d 解释: 我更喜欢用git branch -vv 替换git branch --merged 来显示状态(已消失),因为之前的git branch --merged 也可以显示主
【解决方案15】:

我认为没有内置命令可以执行此操作,但可以安全地执行以下操作:

git checkout master
git branch -d bug-fix-a

当你使用-d 时,git 将拒绝删除该分支,除非它完全合并到HEAD 或其上游远程跟踪分支中。因此,您始终可以遍历git for-each-ref 的输出并尝试删除每个分支。这种方法的问题在于,我怀疑您可能不希望 bug-fix-d 被删除,因为 origin/bug-fix-d 包含其历史记录。相反,您可以创建如下脚本:

#!/bin/sh

git checkout master &&
for r in $(git for-each-ref refs/heads --format='%(refname:short)')
do
  if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ]
  then
    if [ "$r" != "master" ]
    then
      git branch -d "$r"
    fi
  fi
done

警告:我没有测试过这个脚本 - 请谨慎使用...

【讨论】:

  • 我冒昧地编辑了脚本。仍然不会提供任何保证,但是,它现在运行并且似乎可以工作。
【解决方案16】:

可能对一些人有用,简单的一行来清除除 master 和 develop 之外的所有本地分支

git branch | grep -v "master" | grep -v "develop" | xargs git branch -D

【讨论】:

  • 很棒的答案!我喜欢在承诺添加命令的删除部分之前如何轻松地使用'git branch | grep -v "master" | grep -v "develop" 之类的东西。 ??
  • 但这并不能回答上面的问题。即使远程仍然存在,这也会删除分支。
【解决方案17】:

虽然上面的答案涵盖了如何手动修剪分支,但这个答案增加了自动化来解决这个问题。 git 现在有一个新设置,可以为每个获取操作修剪不再远程的陈旧分支。这很棒,因为我们不再需要在每次删除分支时手动调用 remote prunegit pull 也调用 git fetch)。

为每次提取启用修剪行为

要在全局配置中启用此功能:

git config --global fetch.prune true

让事情自动发生意味着您可以忘记在新机器上添加此设置。它只是工作。

为特定遥控器上的每次提取启用修剪行为

git config --global remote.<name>.prune true

本地自动修剪

我们也可以在没有--global 标志的情况下对本地修剪应用相同的命令。

.gitconfig

以上命令适用于全局和本地.gitconfig,如下:

...
[fetch]
    prune = true

我可以建议将其添加到 ansible 配置或您的 dotfiles 存储库 (.gitconfig) 以便将来自动进行设置。

配置设置在每次提取时调用以下命令:

git remote prune <remote name>

总结

要将引用作为正常工作流程的一部分而无需记住运行它,请在配置中设置 fetch.prune 全局或 remote.&lt;name&gt;.prune per-remote。见git-config

【讨论】:

    【解决方案18】:

    这些都不适合我。我想要一些可以清除所有跟踪远程分支的本地分支的东西,在origin 上,远程分支已被删除 (gone)。我不想删除从未设置为跟踪远程分支的本地分支(即:我的本地开发分支)。我还想要一个简单的单行代码,它只使用git 或其他简单的 CLI 工具,而不是编写自定义脚本。我最终使用了一些grepawk 来制作这个简单的命令。

    这最终是我的~/.gitconfig

    [alias]
      prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D
    

    这是一个git config --global ... 命令,可以轻松地将其添加为git prune-branches

    git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'
    

    注意:在配置命令中,我使用-d 选项来代替git branch 而不是-D,就像我在实际配置中所做的那样。我使用-D 是因为我不想听到 Git 抱怨未合并的分支。您可能也需要此功能。如果是这样,只需在该配置命令的末尾使用-D 而不是-d

    【讨论】:

    • 我喜欢 git 别名方法。快速提问:为什么要为git branch -vv 和grep 为: gone] 而不是为git branch -v 和grep 为[gone]
    • @lalibi,好问题。我不记得了。我怀疑只有一个v 没有显示某些东西。如果git branch -v | grep '[gone]' 适合你,那就去吧。它确实看起来更干净一些。
    【解决方案19】:
    grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d
    

    上述命令可用于获取远程合并和删除的分支,并删除远程不再可用的本地分支

    【讨论】:

    • 目前为止最好的解决方案,虽然我把它改成grep gone &lt;(git branch -v) | cut -d ' ' -f 3 | xargs git branch -D强制删除所有
    • 如果您的任何分支名称碰巧在其中的任何位置包含子字符串 gone(例如 usingonefunction),则会很危险。
    【解决方案20】:

    我发现基于 Powershell 的解决方案比这里的许多实现更清晰。

    # prune deleted remoted branches
    git fetch -p
    
    # get all branches and their corresponding remote status
    # deleted remotes will be marked [gone]
    git branch -v |
      #find ones marked [gone], capture branchName
      select-string -Pattern '^  (?<branchName>\S+)\s+\w+ \[gone\]' | 
      foreach-object{ 
         #delete the captured branchname.
         git branch -D $_.Matches[0].Groups['branchName']
      }
    

    【讨论】:

      【解决方案21】:

      根据上面的信息,这对我有用:

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

      它会删除所有远程为': gone] ' 的本地分支。

      【讨论】:

      • 看起来这也会删除在最后一个提交消息中“消失”的任何分支。
      • 它还将删除任何名称中包含gone 的任何分支。
      • "git branch -D git branch -vv | grep ':gone] ' | awk '{print $1}' | xargs`" 这对我有用。
      【解决方案22】:

      numberofotheranswers这里大量绘制,我最终得到了以下内容(我相信只有 git 2.13 及更高版本),它应该适用于任何类 UNIX 外壳:

      git for-each-ref --shell --format='ref=%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)' refs/heads | while read entry; do eval "$entry"; [ ! -z "$ref" ] && git update-ref -d "$ref" && echo "deleted $ref"; done
      

      这特别是使用for-each-ref 而不是branch(因为branch 是为人类可读输出设计的“瓷器”命令,而不是机器处理)并使用其--shell 参数来获得正确转义的输出(这让我们不必担心 ref 名称中的任何字符)。

      【讨论】:

      • 它对我有用,但如果你能解释一下命令中的其他步骤在做什么,那就太好了。例如我不知道[ ! -z "$ref" ] 是什么意思。我认为多班轮已经有所帮助。但仍然感谢您的意见!
      【解决方案23】:

      基于Git Tip: Deleting Old Local Branches,它看起来类似于jason.rickman's solution,为此我使用Bash 实现了一个名为git gone 的自定义命令:

      $ git gone
      usage: git gone [-pndD] [<branch>=origin]
      OPTIONS
        -p  prune remote branch
        -n  dry run: list the gone branches
        -d  delete the gone branches
        -D  delete the gone branches forcefully
      
      EXAMPLES
      git gone -pn    prune and dry run
      git gone -d     delete the gone branches
      

      git gone -pn 结合修剪和列出“消失”的分支:

      $ git gone -pn
        bport/fix-server-broadcast         b472d5d2b [origin/bport/fix-server-broadcast: gone] Bump modules
        fport/rangepos                     45c857d15 [origin/fport/rangepos: gone] Bump modules
      

      然后您可以使用git gone -dgit gone -D 扣动扳机。

      注意事项

      • 我使用的正则表达式是"$BRANCH/.*: gone]",其中$BRANCH 通常是origin。如果您的 Git 输出本地化为法语等,这可能不起作用。
      • Sebastian Wiesner 还为 Windows 用户将其移植到 Rust。那个也叫git gone

      【讨论】:

      • 这应该是公认的答案 - git gone 看起来像 git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d 的别名,它解决了 OP 的问题。
      【解决方案24】:

      我喜欢使用管道,因为它使命令更易于阅读。

      如果您想删除除 master 之外的所有分支,这是我的解决方案。

      git branch | grep -v master | xargs -n 1 git branch -D
      

      要删除符合您条件的其他分支,请修改第一个和第二个块。

      git branch --merged | grep feature_name | xargs -n 1 git branch -D
      

      【讨论】:

      • 可以简化一点:git branch --merged | grep -vE 'main|master|\\*' | xargs -n 1 git branch -D"
      【解决方案25】:

      也许这个命令就是你想要的。

      运行后:

      git remote prune origin
      

      然后运行:

      diff <(git branch | sed -e 's/*/ /g') <(git branch -r | sed -e 's/origin\///g') | grep '^<'
      

      这将显示所有不在 (git branch -r) 但在 (git branch) 中的分支

      这个方法有问题,还会显示本地没有推送过的分支

      【讨论】:

        【解决方案26】:

        一种更简单的解决方案,适用于 Windows 或其他不想/无法编写命令行脚本或不想使用 PowerShell 的人。

        将分支列表转储到文件中 git branch &gt; branches.txt
        (或git branch --merged &gt; branches.txt,如果你是腰带和吊带类型; git branch -d 将防止删除未合并的分支)

        在编辑器中打开该文件并合并所有行(我使用了 sublime 文本,所以突出显示所有并按ctrl+j

        在您的分支列表前添加git branch -d

        全选,复制,粘贴(在windows cmd窗口右键)到命令行中。

        【讨论】:

          【解决方案27】:

          真正的挑战是维护者何时压缩提交。那么,使用--merged等git内置功能的解决方案就无济于事了。

          git-delete-merged-branches 工具可以方便地删除分支。我特别喜欢互动模式。

          安装(需要python3):

          pip install git-delete-merged-branches
          

          然后执行

          git-delete-merged-branches --effort=3
          

          --effort=3 对于启用压缩分支的删除很重要。

          替代方案

          【讨论】:

            【解决方案28】:

            我想出了这个 bash 脚本。它始终保持分支developqamaster

            git-clear() {
              git pull -a > /dev/null
            
              local branches=$(git branch --merged | grep -v 'develop' | grep -v 'master' | grep -v 'qa' | sed 's/^\s*//')
              branches=(${branches//;/ })
            
              if [ -z $branches ]; then
                echo 'No branches to delete...'
                return;
              fi
            
              echo $branches
            
              echo 'Do you want to delete these merged branches? (y/n)'
              read yn
              case $yn in
                  [^Yy]* ) return;;
              esac
            
              echo 'Deleting...'
            
              git remote prune origin
              echo $branches | xargs git branch -d
              git branch -vv
            }
            

            【讨论】:

              【解决方案29】:

              我使用一种简短的方法来解决问题,我建议您也这样做,因为它可以节省一些时间并让您获得更多的知名度

              只需将以下 sn-p 添加到您的 .bashrc(macos 上的 .bashprofile)中即可。

              git-cleaner() { git fetch --all --prune && git branch --merged | grep -v -E "\bmaster|preprod|dmz\b" | xargs -n 1 git branch -d ;};
              
              1. 获取所有遥控器
              2. 仅从 git 获取合并的分支
              3. 从此列表中删除“受保护/重要”分支
              4. 删除其余部分(例如,清理和合并的分支)

              您必须编辑 grep 正则表达式以满足您的需要(在这里,它可以防止 master、preprod 和 dmz 被删除)

              【讨论】:

                【解决方案30】:

                这对我有用:

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

                【讨论】:

                • 哦,我把这个贴在了……刚刚在评论帖子时看到了这个。但是你真的可以指出提供这个命令的人,而不是把它当作你的!
                • 我是从论坛上得到的,不要自作聪明,只接受答案或忽略它
                • 即使你做不到……反正……不是来和你讨论这个的。正如你所说..接受我的评论或忽略它;)
                猜你喜欢
                • 1970-01-01
                • 2014-06-09
                • 1970-01-01
                • 2017-11-12
                • 1970-01-01
                • 2013-04-30
                • 2012-10-15
                • 2016-07-08
                相关资源
                最近更新 更多