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

例子:

分支机构(本地和远程)

主人原始/主起源/bug-fix-a起源/bug-fix-b起源/bug-fix-c

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

分支机构(本地和远程)

主人bug-fix-abug-fix-b型原始/主起源/bug-fix-a起源/bug-fix-b起源/bug-fix-c

现在我有本地分支机构master,bug-fix-a,bug--fix-b。主分支维护者将把我的更改合并到主分支中,并删除他已经合并的所有分支。

因此,当前状态为:

分支机构(本地和远程)

主人bug-fix-abug-fix-b型原始/主起源/bug-fix-c

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

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


当前回答

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

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

其他回答

列出远程分支现在已消失的所有本地分支

#!/bin/sh
LC_ALL=C git for-each-ref --format='%(refname:short) %(upstream:track)' refs/heads/ |\
    sed -n '/ *\[gone\].*$/{s@@@;p}'

然后通过管道将其导入xargs git分支-D或-D。

此解决方案应与POSIX兼容。没有特定于shell的东西,只有POSIX兼容的sed/xargs。

LC_ALL=C通过强制英语使脚本语言保持中立对于每个引用,使用管道命令--format='%(refname:short)%(upstream:track)输出分支名称跟踪信息参考/仅负责本地分支机构sed-n'/*\[gone\].*$/匹配跟踪信息[gone],该信息不是有效分支名称的一部分,因此无需担心{s@@@;p}删除跟踪部分并仅打印这些行

nb:分支不能包含空格,因此我们不需要对xargs进行任何清理。

我想出了这个bash脚本。它总是保持分支的发展,qa,master。

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
}

最安全的方法是对每个ref使用带有插值变量%(upstream:track)的“管道”命令git,当分支不再位于远程时,该变量将消失:

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

这种方法比使用“瓷”命令更安全,因为不会有意外匹配提交消息部分的风险。下面是一个使用“瓷”git命令的版本:

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

这种工作方式是在命令之后

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

这是脚本迭代的内容。

所有这些都不适合我。我想要一些东西来清除所有跟踪远程分支的本地分支,在源位置,远程分支已被删除(消失)。我不想删除从未设置为跟踪远程分支的本地分支(即:我的本地dev分支)。我还想要一个简单的一行程序,它只使用git或其他简单的CLI工具,而不是编写自定义脚本。我最后使用了一点grep和awk来生成这个简单的命令。

这最终是我的~/.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分支的命令:

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

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

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

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

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

进一步阅读:

为什么不应该在脚本中解析git分支输出。跟踪分支以及git remote prune、git prune和git fetch--prune之间的差异


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

git fetch--prune(或git fetch-p,它是一个别名,或git prune remote origin,它在不获取的情况下执行相同的操作,并且可能不是您大多数时候想要的)。注意报告为已删除的任何远程分支。或者,为了稍后找到它们,可以使用gitbranch-v(任何孤立的跟踪分支都将标记为“[gone]”)。每个孤立跟踪分支上的gitbranch-d[分支名称]

(这是其他一些答案提出的)。

如果你想编写一个解决方案的脚本,那么每个ref都是你的出发点,就像Mark Longair在这里的回答和对另一个问题的回答一样,但我看不出不编写shell脚本循环或使用xargs之类的方法来利用它。


背景说明

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

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

有时,有人删除了遥控器上的功能/X。从那一刻起,您就剩下了本地功能/X(您可能不想再使用它了,因为功能X的工作大概已经完成了)和远程/原点/功能/X,这肯定是无用的,因为它的唯一目的是记住服务器分支的状态。

Git将允许您自动清理冗余的remotes/origin/feature/X,这就是gitfetch-prime所做的,但由于某些原因,它不允许您自动删除自己的功能/X。。。即使您的feature/X仍然包含孤立的跟踪信息,因此它具有识别已完全合并的前跟踪分支的信息。(毕竟,它可以为您提供信息,让您自己动手操作。)