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

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

我该怎么做呢?


当前回答

如果使用Windows和Powershell,您可以使用以下命令删除已合并到当前签出的分支中的所有本地分支:

git branch --merged | ? {$_[0] -ne '*'} | % {$_.trim()} | % {git branch -d $_}

解释

列出当前分支和已合并到其中的分支 过滤掉当前分支 清除git输出中每个剩余分支名称的前导或尾随空格 删除合并的本地分支

值得先运行git分支——自行合并,以确保它只会删除你希望它删除的东西。

(从http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/移植/自动化。)

其他回答

修剪完成后,你可以使用git branch -r获取远程分支的列表。带有远程跟踪分支的分支列表可以使用git branch -vv检索。因此,使用这两个列表,您可以找到不在远程列表中的远程跟踪分支。

这一行应该做的把戏(需要bash或zsh,不会与标准的Bourne shell工作):

git fetch -p ; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

该字符串获取远程分支的列表,并通过标准输入将其传递给egrep。并过滤具有远程跟踪分支的分支(使用git branch -vv并过滤那些具有origin的分支),然后获得输出的第一列,这将是分支名称。最后将所有分支名称传递给delete branch命令。

由于它使用的是-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”。

在git帮助获取提供的信息中,有这样一个小项目:

 -p, --prune
        After fetching, remove any remote-tracking branches which no longer exist on the remote.

也许,git fetch -p是你要找的?

编辑:好吧,对于那些3年后还在争论这个答案的人,这里有一些关于我为什么给出这个答案的更多信息……

首先,OP说他们想“删除那些从远程分支创建的本地分支(这些分支不在远程上了)”。这在git中并不是完全可能的。举个例子。

假设我在中央服务器上有一个回购,它有两个分支,称为a和B。如果我将该回购克隆到我的本地系统,我的克隆将有本地引用(还不是实际的分支)称为origin/ a和origin/B。现在假设我做了以下事情:

git checkout -b A origin/A
git checkout -b Z origin/B
git checkout -b C <some hash>

这里的相关事实是,出于某种原因,我选择在我的本地回购上创建一个分支,该分支的名称与其起源不同,并且我还有一个本地分支,它(还)不存在于起源回购上。

Now let's say I remove both the A and B branches on the remote repo and update my local repo (git fetch of some form), which causes my local refs origin/A and origin/B to disappear. Now, my local repo has three branches still, A, Z, and C. None of these have a corresponding branch on the remote repo. Two of them were "created from ... remote branches", but even if I know that there used to be a branch called B on the origin, I have no way to know that Z was created from B, because it was renamed in the process, probably for a good reason. So, really, without some external process recording branch origin metadata, or a human who knows the history, it is impossible to tell which of the three branches, if any, the OP is targeting for removal. Without some external information that git does not automatically maintain for you, git fetch -p is about as close as you can get, and any automatic method for literally attempting what the OP asked runs the risk of either deleting too many branches, or missing some that the OP would otherwise want deleted.

还有其他的场景,比如,如果我在origin/A之外创建三个独立的分支,以测试三种不同的方法,然后origin/A消失了。现在我有三个分支,它们显然不能全部匹配名称,但它们是从origin/A创建的,因此OPs问题的字面解释需要删除所有三个分支。然而,如果你能找到一种可靠的方法来匹配它们,这可能并不理想……

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答案的变体,我将以下内容作为~/的别名添加到~/。gitconfig文件:

pruneitgood = "!f() { \
    git remote prune origin; \
    git branch -vv | perl -nae 'system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}'; \
}; f"

这样,一个简单的git pruneitgood就可以清理合并后不再需要的本地和远程分支。