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

例子:

分支机构(本地和远程)

主人原始/主起源/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。


当前回答

所有这些都不适合我。我想要一些东西来清除所有跟踪远程分支的本地分支,在源位置,远程分支已被删除(消失)。我不想删除从未设置为跟踪远程分支的本地分支(即:我的本地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。

其他回答

这些答案中的大多数实际上并没有回答最初的问题。我做了大量的挖掘,这是我找到的最干净的解决方案。这是一个稍微更彻底的答案:

查看默认分支。通常是git结账大师运行git fetch-p&&git branch-vv|awk'/:gone]/{print$1}'|xargs git branch-d

说明:

通过修剪跟踪分支,然后在gitbranch-vv中删除显示它们已“消失”的本地分支。

笔记:

如果您的语言设置为英语以外的语言,则需要更改为相应的单词。仅本地的分支将不会被触摸。已在远程删除但未合并的分支将显示通知,但不会在本地删除。如果您想删除这些,也可以将-d更改为-d。

我想出了这个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
}

在大多数其他解决方案中,模式匹配“gone”对我来说有点可怕。为了更安全,这使用--format标志来提取每个分支的上游跟踪状态。

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

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

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

删除已合并到主控形状中的所有分支,但不要尝试删除主控形状本身:

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

或添加别名:

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

说明:

git结帐主结帐主分支

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

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

gitbranch-d$(gitbranch-master--merged|grepmaster-v)删除已合并到master中的所有分支,但不要尝试删除master本身

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

#!/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进行任何清理。