使用git远程修剪原点,我可以删除不在远程上的本地分支。

但是我还想删除从这些远程分支创建的本地分支(检查它们是否未合并会很好)。

我该怎么做呢?


当前回答

这适用于我使用git 2.21.0 -它删除本地跟踪分支,这些分支合并到HEAD中,我之前在push上—set-upstream(我使用push.default=upstream,因为它最适合多个远程),并且上游分支已经被fetch—prune(或隐式地如果fetch。修剪=true在git配置):

git branch -vv --merged | grep ': gone]' | awk '{print $1}' | xargs git branch -d

-merged和-d的使用使得这是一个非常“安全”的删除。更激进的版本可以放弃-merged并使用-D

其他回答

I wanted something that would purge all local branches that were tracking a remote branch, on origin, where the remote branch has been deleted (gone). I did not want to delete local branches that were never set up to track a remote branch (i.e.: my local dev branches). Also, I wanted a simple one-liner that just uses git, or other simple CLI tools, rather than writing custom scripts. I ended up using a bit of grep and awk to make this simple command, then added it as an alias in my ~/.gitconfig.

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

这是一个git配置-全局…命令可以方便地将其添加为git prune-branches:

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

注意:对git分支使用-D标志可能非常危险。所以,在上面的config命令中,我使用-d选项来git分支而不是-d;我在实际配置中使用-D。我使用-D是因为我不想听到Git抱怨未合并的分支,我只是想让它们消失。您可能也需要这个功能。如果是这样,只需在配置命令的末尾使用-D而不是-D。

以下是@wisbucky对Windows用户的回答:

for /f "tokens=1" %i in ('git branch -vv ^| findstr ": gone]"') DO git branch %i -d

我使用posh-git,不幸的是PS不喜欢裸体for,所以我创建了一个普通的'ol命令脚本,名为PruneOrphanBranches.cmd:

@ECHO OFF
for /f "tokens=1" %%i in ('git branch -vv ^| findstr ": gone]"') DO CALL :ProcessBranch %%i %1

GOTO :EOF

:ProcessBranch
IF /I "%2%"=="-d" (
    git branch %1 %2
) ELSE (
    CALL :OutputMessage %1
)
GOTO :EOF

:OutputMessage
ECHO Will delete branch [%1] 
GOTO :EOF

:EOF

不带参数调用它以查看列表,然后用“-d”调用它来执行实际的删除或对任何没有完全合并但无论如何都想删除的分支执行“-d”。

这个命令和下面的脚本可以在Linux和Windows中使用Git Bash (MinGW)。

最好使用git的内部命令,这样注释或名称就不会意外地匹配并删除您不想删除的分支。git for-each-ref的格式选项可以使用许多内部“原子”来输出所需的信息。这样,我们就不必依赖管道连接到awk或grep来检查输出中的正则表达式,因为它可能包含不必要的信息。

下面的命令只使用git for-each-ref的内部低级命令来列出孤立的本地分支。一旦你有了这些,你可以管道到git分支-D。此外,别忘了先修剪和获取远程引用,否则它将找不到任何匹配:

git fetch -p
git for-each-ref --format '%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' 'refs/heads/**' | xargs -r git branch -D

以下是分类:

Git fetch -p -删除已删除的引用,并从远程获取新的引用

Git for-each-ref——format -列出使用特定输出格式的所有引用。

%(if: = =[gone])%(upstream:track) -仅在上游跟踪分支“[gone]”时输出。

%(then)%(refname:short)%(end) -输出分支名称(当跟踪消失时)。

Refs /heads/** -限制头部引用(为了提高效率)。

| xargs -r git分支- d管道输出作为参数删除。-r表示忽略空白输入。


就其本身而言,这个解很长,很难输入,也很难记住。幸运的是,向git添加自定义命令很容易。下面的脚本使用了上面的相同命令,但是它允许用户使用——dry-run选项查看将选择哪些分支。

我将我的文件命名为git-prune-local,并将其放在包含在PATH中的文件夹中。它还需要执行权限(chmod 755 git-prune-local)。

Git自动查找可执行文件,如Git -[command]。这样,你只需要输入git prune-local来删除正确的分支。

git-prune-local

#!/bin/sh

if [ $# -gt 1 ] || ([ ! -z $1 ] && [ $1 != "--dry-run" ])
then
    echo "Usage: git prune-local [--dry-run]"
    exit
fi

git fetch -p --quiet
branchesToDelete=$(git for-each-ref --format '%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' 'refs/heads/**')

while read -r branch
do
    if [ ! -z $branch ]
    then
        if [ ! -z $1 ]
        then
            echo $branch
        else
            git branch -D $branch
        fi
    fi
done <<< "$branchesToDelete"

除了Schleis的答案(它工作得很完美),它还可以集成到Visual Studio中,所以在VS中打开git repo时修剪本地分支非常简单。

您可以使用外部工具功能调用sh.exe (git bash)与特定的目录和命令。它位于工具>外部工具菜单选项中(在VS 2022 17.1.0中)。我使用的参数如下:

命令:{Path-To-Git-Installation-Location} \ bin \ sh.exe

参数:——cd=$(SolutionDir) -c "git fetch -p;Git branch -r | awk '{print $1}' | egrep -v -f /dev/ fg /0 <(Git branch -vv | grep origin) | awk '{print $1}' | xargs Git branch -d"

初始目录:$(SolutionDir)

Git修剪本地分支的截图

值得注意的是,只有当你在VS中打开的解决方案在git repo目录中时,这才会起作用。

最后提醒-这可以通过Visual Studio的按键绑定用户界面在设置>通用>键盘和搜索工具进行按键绑定。ExternalCommand[n],其中n是外部命令表中的位置,您有这个外部工具的位置(它们可以在工具>外部工具对话框中重新排序)。请看下面的截图。

键盘绑定外部工具命令

当遥控器本身不再存在时,我没有发现这里的答案有用。 我一直看到不存在的遥控器分支,但没有找到一个git命令来删除它们。

对我来说,解决方案是转到.git\refs\remotes目录,直接删除不再相关的文件。文件结构很容易理解。它与git branch -r的结构相同。