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

例子:

分支机构(本地和远程)

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


当前回答

真正的挑战是当维护者压缩提交时。然后,使用git内置功能(如--merged)的解决方案没有帮助。

gitdelete合并分支工具允许方便地删除分支。我特别喜欢互动模式。

安装(需要python3):

pip install git-delete-merged-branches

然后执行

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

--努力=3对于能够删除挤压的分支很重要。

选择

@teppeis/git delete squashed:安装node.js后,执行npx@teppeis/git delete squushed。支持主分支。git delete squashed:未维护:主分支的未命中功能@teppeis/git delete squashed基于此。

其他回答

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

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

有时,你只是想有一个干净的记录,但需要确保能够回到以前在当地分支机构的工作。

如果是这样,最简单的方法可能就是归档当前的本地克隆并创建一个新的克隆。

因此,对于仅具有本地默认分支的存储库X

move X X-2021-11-10
git clone http://...../X

如果您需要完全相同的来源,请询问git

git -C X remote -v

从这里大量的其他答案中,我得出了以下结论(我认为只有2.13和更高的数字),它应该适用于任何类似UNIX的shell:

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

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

虽然上面的答案涵盖了如何手动修剪树枝,但这个答案增加了解决这一问题的自动化。git现在有了一个新设置,可以在每次提取操作中删除不再位于远程的过时分支。这很好,因为我们不再需要在每次删除分支时手动调用远程prune(git pull也调用git fetch)。

为每次提取启用修剪行为

要在全局配置中启用此功能,请执行以下操作:

git config --global fetch.prune true

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

对特定远程设备上的每次提取启用修剪行为

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

本地自动修剪

我们也可以在不使用--global标志的情况下对局部修剪应用相同的命令。

.git配置

上面的命令适用于global和local.gitconfig,如下所示:

...
[fetch]
    prune = true

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

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

git remote prune <remote name>

总结

要将引用作为正常工作流的一部分进行删减而不需要记住运行,请全局或远程设置fetch.prune<name>.在配置中对每个远程进行修剪。请参阅git-config。

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

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