是否有一种简单的方法可以删除所有远程对等分支不再存在的跟踪分支?
例子:
分支机构(本地和远程)
主人原始/主起源/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。
我已经用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()
希望有人觉得它有用,如果我错过了什么,请添加评论。
所有这些都不适合我。我想要一些东西来清除所有跟踪远程分支的本地分支,在源位置,远程分支已被删除(消失)。我不想删除从未设置为跟踪远程分支的本地分支(即:我的本地dev分支)。我还想要一个简单的一行程序,它只使用git或其他简单的CLI工具,而不是编写自定义脚本。我最后使用了一点grep和awk来生成这个简单的命令。
这最终是我的~/.gitconfig:
[alias]
prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D
这里有一个git-config--global。。。用于轻松将其添加为git prune分支的命令:
git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'
注意:在config命令中,我使用-d选项来gitbranch,而不是-d,正如我在实际配置中所做的那样。我使用-D是因为我不想听到Git抱怨未合并的分支。您可能也需要此功能。如果是这样,只需在config命令末尾使用-D而不是-D。
另一个答案。
如果你正在寻找一些新奇的东西,这里是我在fzf中使用的别名。
LANG=C git for-each-ref --sort=-committerdate --format '%(refname:short) %(upstream:track)' refs/heads \
| awk '$2 == "[gone]" {print $1}' \
| fzf --multi --bind ctrl-a:select-all,ctrl-t:toggle-all \
--preview='git log --color=always --graph --format=compact {1}' \
--header='Select [gone] branch to remove' \
--header-first --reverse \
| xargs --no-run-if-empty git branch -d
解释:
强制LANG=C以避免[gone]模式上的本地化对每个引用使用git,以避免git分支中的任何格式更改使用awk过滤。我尝试使用--format=“%(if:equals=[gone])%…”,但这意味着要管理空行。使用fzf选择要删除的分支。添加快捷键:[ctrl-a]选择全部,[ctrl-t]反转选择([tab]照常选择)。您可以使用[enter]进行验证,也可以使用[esc]中止。我使用这个分支选择器作为确认阶段。在右侧显示所选分支的日志(以记住日期和内容…)。我使用下面列出的紧凑格式。您可以使用任何(不太宽)日志格式。--如果为空,则不运行。它不是强制性的,有助于避免在中止进程时出错(与没有分支名称的gitbranch-d相关)。
别名可能看起来很糟糕:
[alias]
gone = "!f() { LANG=C git for-each-ref --sort=-committerdate --format '%(refname:short) %(upstream:track)' refs/heads | awk '$2 == \"[gone]\" {print $1}' | fzf --multi --bind ctrl-a:select-all,ctrl-t:toggle-all --preview='git log --color=always --graph --format=compact {1}' --header='Select [gone] branch to remove' --header-first --reverse | xargs --no-run-if-empty git branch -d ; }; f"
[pretty]
compact = %Cred%h%Creset%C(auto)%d%Creset%n Author: %an <%aE>%n Date: %cd%n %s
(与上文相同,“)
删除已合并到主控形状中的所有分支,但不要尝试删除主控形状本身:
git checkout master&&git pull origin master&&git fetch-p&&git branch-d$(git branch--merged|grep master-v)
或添加别名:
alias gitcleanlocal=“git checkout master&&git pull origin master&&git fetch-p&&git branch-d$(git branch--merged|grep master-v)”
说明:
git结帐主结帐主分支
git pull-origin master确保本地分支合并了所有远程更改
gitfetch-p删除对已删除的远程分支的引用
gitbranch-d$(gitbranch-master--merged|grepmaster-v)删除已合并到master中的所有分支,但不要尝试删除master本身