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

例子:

分支机构(本地和远程)

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


当前回答

看来每个人都有解决办法。好吧,如果你喜欢一个带有TUI(基于文本的用户界面)的交互式工具,我写了一个叫做gitxcleaner的工具。它可以找到合并的分支、重新基础的分支(使用相同的提交消息提交)、修剪的分支或手动选择的分支。

https://github.com/lzap/git-xcleaner

其他回答

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

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

当您使用-d时,git将拒绝删除分支,除非它完全合并到HEAD或其上游远程跟踪分支中。因此,您可以始终循环每个ref的git输出,并尝试删除每个分支。这种方法的问题是,我怀疑您可能不希望因为origin/bug-fix-d包含其历史而删除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

警告:我尚未测试此脚本-请小心使用。。。

看来每个人都有解决办法。好吧,如果你喜欢一个带有TUI(基于文本的用户界面)的交互式工具,我写了一个叫做gitxcleaner的工具。它可以找到合并的分支、重新基础的分支(使用相同的提交消息提交)、修剪的分支或手动选择的分支。

https://github.com/lzap/git-xcleaner

我已经用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()

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

我使用了一个简短的方法来完成这项任务,我建议你也这样做,因为这样可以节省一些时间,并提高你的可见度

只需将以下代码段添加到.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 ;};

获取所有遥控器仅从git中获取合并的分支从此列表中删除“受保护/重要”分支删除其余部分(例如,清理和合并的分支)

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

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

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

说明:

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

笔记:

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