从 git 中清除多余的分支

Bjö*_*ist 4 git version-control github git-pull branching-and-merging

这是场景:有人有一个我已经分叉的 git 存储库(如果重要的话,在 github 上)。在我的分支中,我创建了许多分支,其中包含上游已拉取的更改。或者在某些情况下应用我的分支的差异而不是正确拉动分支。

我想要找到的是我所有分支的列表,这些分支已经完全合并到上游主分支中。这样我就可以安全地删除这些分支,因为git branch其他工具列出了 30 多个分支,而且看起来很杂乱。

我想我正确地解释了为什么这个问题与链接的问题不同:或者在某些情况下应用了我的分支的差异而不是正确地拉动分支例如git branch --merged不是一个完整的答案,但是哦......

AD7*_*six 5

根据您希望这样做的频率,您可能希望手动执行(首先解释)或编写脚本(随后解释)。

在下面,假设有一个“上游”远程指向您分叉的存储库,例如:

$ git remote -v
origin git@github.com:you/repo.git (fetch)
origin git@github.com:you/repo.git (push)
upstream git://github.com/original/repo.git (fetch)
upstream git://github.com/original/repo.git (push)
Run Code Online (Sandbox Code Playgroud)

列出所有合并的本地分支

要获取已经与上游 master 合并的分支列表:

$ git fetch upstream
$ git branch --merged upstream/master
my-feature
my-other-feature
master
Run Code Online (Sandbox Code Playgroud)

然后您可以删除它们:

$ git branch -d my-feature
$ git branch -d my-other-feature
Run Code Online (Sandbox Code Playgroud)

如果更改是手动应用的,它们可能不在上游历史记录中,因此可能不会列出具有等效代码更改的本地分支。出现这种情况的分支应手动检测。

删除对不存在的远程分支的本地引用

如果您有代表已被删除的远程分支的本地分支(该分支用于拉取请求,合并拉取请求后您通过 github 的 gui 删除了该分支),则有一个标准的 git 命令用于清理这些分支引用:

$ git remote prune origin
Run Code Online (Sandbox Code Playgroud)

删除已合并的远程分支

要获取已合并的 fork 中的远程分支列表,类似于第一个命令 - 但使用-r开关(远程分支):

$ git branch -r --merged upstream/master
origin/my-feature
origin/my-other-feature
upstream/someone-elses-branch
Run Code Online (Sandbox Code Playgroud)

删除你自己已经合并的远程分支:

$ git push origin :my-feature
$ git push --delete origin my-other-feature # equivalent, just different syntax
Run Code Online (Sandbox Code Playgroud)

脚本解决方案

使用脚本化解决方案时要小心,因为很容易意外删除您不打算删除的分支。也就是说,请记住分支只是引用/名称 - 删除分支(意外)并不意味着内容丢失,它们可以轻松恢复(git reflog例如检查)。

下面的脚本删除以“功能”开头的本地和远程分支 - 例如,这是确保您自己的最新主分支不会被意外删除的一种方法。

#!/bin/bash
# E.g. save as ~/bin/git-cleanup, make executable and have ~/bin in your path
# call as `git cleanup`

echo -n "Fetching latest ... "
git fetch origin
git fetch upstream
echo "done"

echo "Deleting merged local feature branches ... "
branches=`git branch --no-color --merged upstream/master`
for branch in $branches;
do
    if [[ "$branch" =~ ^feature ]]; then
        git branch -d $branch;
    fi
done
echo "done"

echo "Deleting local refs to remote branches that don't exist ... "
git remote prune origin
git remote prune upstream
echo "done"

echo "Deleting merged remote feature and hotfix branches ... "
branches=`git branch -r --no-color --merged upstream/master`
for branch in $branches;
do
    if [[ "$branch" =~ ^(origin)\/(feature.*$) ]]; then
        remote=${BASH_REMATCH[1]};
        branch=${BASH_REMATCH[2]};
        git push $remote :$branch;
    fi
done

echo "done"

echo ""
echo "all finished"
Run Code Online (Sandbox Code Playgroud)