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

例子:

分支机构(本地和远程)

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


当前回答

TL;博士:

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

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

解释

gitfetch-p将删除远程上不再存在的所有分支gitbranch-vv将打印本地分支,修剪后的分支将标记为已删除grep“:gone]”仅选择已删除的分支awk“{print$1}”筛选输出以仅显示分支的名称xargs git branch-D将循环所有行(分支)并强制删除该分支

为什么选择gitbranch-D而不是gitbranch-D,否则对于未完全合并的分支,您将拥有。

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

其他回答

另一个答案。

如果你正在寻找一些新奇的东西,这里是我在fzf中使用的别名。

LANG=C git for-each-ref --sort=-committerdate --format '%(refname:short) %(upstream:track)' refs/heads \
  | awk '$2 == "[gone]" {print $1}' \
  | fzf --multi --bind ctrl-a:select-all,ctrl-t:toggle-all \
        --preview='git log --color=always --graph --format=compact {1}' \
        --header='Select [gone] branch to remove' \
        --header-first --reverse \
  | xargs --no-run-if-empty git branch -d

解释:

强制LANG=C以避免[gone]模式上的本地化对每个引用使用git,以避免git分支中的任何格式更改使用awk过滤。我尝试使用--format=“%(if:equals=[gone])%…”,但这意味着要管理空行。使用fzf选择要删除的分支。添加快捷键:[ctrl-a]选择全部,[ctrl-t]反转选择([tab]照常选择)。您可以使用[enter]进行验证,也可以使用[esc]中止。我使用这个分支选择器作为确认阶段。在右侧显示所选分支的日志(以记住日期和内容…)。我使用下面列出的紧凑格式。您可以使用任何(不太宽)日志格式。--如果为空,则不运行。它不是强制性的,有助于避免在中止进程时出错(与没有分支名称的gitbranch-d相关)。

别名可能看起来很糟糕:

[alias]
      gone = "!f() { LANG=C git for-each-ref --sort=-committerdate --format '%(refname:short) %(upstream:track)' refs/heads | awk '$2 == \"[gone]\" {print $1}' | fzf --multi --bind ctrl-a:select-all,ctrl-t:toggle-all --preview='git log --color=always --graph --format=compact {1}' --header='Select [gone] branch to remove' --header-first --reverse | xargs --no-run-if-empty git branch -d ; }; f"
[pretty]
      compact = %Cred%h%Creset%C(auto)%d%Creset%n  Author: %an <%aE>%n  Date:  %cd%n     %s

(与上文相同,“)

我已经用GitPython编写了一个Python脚本来删除远程不存在的本地分支。

    import git
    import subprocess
    from git.exc import GitCommandError
    import os

    def delete_merged_branches():
        current_dir = input("Enter repository directory:")
        repo = git.Repo(current_dir)
        git_command = git.Git(current_dir)

        # fetch the remote with prune, this will delete the remote references in local.
        for remote in repo.remotes:
            remote.fetch(prune=True)
        
        local_branches = [branch.name for branch in repo.branches]
        deleted_branches = []

        # deleted_branches are the branches which are deleted on remote but exists on local.
        for branch in local_branches:
            try:
                remote_name = 'origin/'+ branch
                repo.git.checkout(remote_name)
            except GitCommandError:
            # if the remote reference is not present, it means the branch is deleted on remote.
                deleted_branches.append(branch)
            
        for branch in deleted_branches:
            print("Deleting branch:"+branch)
            git_command.execute(["git", "branch", "-D",branch])

    
        # clean up the work flow.
        repo.git.checkout('master')
        repo.git.pull()

    if __name__ == '__main__':
        delete_merged_branches()

希望有人觉得它有用,如果我错过了什么,请添加评论。

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

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

这将删除本地不存在的所有远程分支(在ruby中):

bs = `git branch`.split; bs2 = `git branch -r | grep origin`.split.reject { |b| bs.include?(b.split('/')[1..-1].join('/')) }; bs2.each { |b| puts `git  push origin --delete #{b.split('/')[1..-1].join('/')}` }

解释:

# local branches
bs = `git branch`.split
# remote branches
bs2 = `git branch -r | grep origin`.split
# reject the branches that are present locally (removes origin/ in front)
bs2.reject! { |b| bs.include?(b.split('/')[1..-1].join('/')) }
# deletes the branches (removes origin/ in front)
bs2.each { |b| puts `git  push origin --delete #{b.split('/')[1..-1].join('/')}` }

我不确定要用多久,但我现在确实使用git-up,这可以解决这个问题。

我做了git,它开始跟踪新的分支并删除旧的分支。

为了清楚起见,这不是现成的git命令-https://github.com/aanand/git-up

顺便说一句,它还藏着脏树,只需把它捡起来就可以重新放回原处。

希望对某人有用