如何删除已合并的分支?我可以一次删除所有分支,而不是逐个删除每个分支吗?
当前回答
下面创建一个别名gitcleanup,其中包含一个可选参数分支。默认情况下,它使用远程源的默认分支。已合并到此中的每个分支都将被删除。还有一个-d/-dryrun选项,用于显示将删除的内容。
安装程序
git config --global alias.cleanup '!COMMAND="git branch -D"; while [[ $# -gt 0 ]]; do case "$1" in -d|--dryrun) COMMAND="echo"; shift; ;; *) MAIN_BRANCH="$1"; shift;; esac; done; MAIN_BRANCH="${MAIN_BRANCH:-$(git symbolic-ref refs/remotes/origin/HEAD)}"; git for-each-ref --merged="$MAIN_BRANCH" --no-contains="$MAIN_BRANCH" --format="%(refname:short)" refs/heads/ | xargs -n1 -r $COMMAND;#'
用法:
git cleanup # delete all branches that have been merged into origin/HEAD
git cleanup master2 # delete all branches that have been merged into master2
git cleanup master2 -d # do a dryrun (show names of branches that would be delted)
可读代码
谁能读到那句“oneliner”?好了,给你
COMMAND="git branch -D";
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--dryrun)
COMMAND="echo";
shift;
;;
*)
MAIN_BRANCH="$1";
shift
;;
esac;
done;
MAIN_BRANCH="${MAIN_BRANCH:-$(git symbolic-ref refs/remotes/origin/HEAD)}";
git for-each-ref --merged="$MAIN_BRANCH" --no-contains="$MAIN_BRANCH" --format="%(refname:short)" refs/heads/ | xargs -n1 -r $COMMAND;
#
与其他答案有什么不同?
使用--no contains选项过滤掉标识分支(所有其他被删除的分支都已合并到其中的分支),而不是grep-v(如果您特定于分支并指定refs/heads/master,则效果更好)使用远程HEAD检查默认分支名称具有一个参数,用于指定要用作合并主节点的分支具有干式运行选项
其他回答
假设我有一个名为upstream的远程和一个origin(GitHub风格,我的fork是origin,upstream是upstream)。
我不想从上游删除任何主机、HEAD或任何内容。我也不想删除开发分支,因为这是我们创建PR的公共分支。
列出所有远程分支,按合并的分支进行筛选:
git branch -r
从该列表中删除包含我知道不想删除的分支名称中的单词的行:
sed '/develop\|master\|HEAD\|upstream/d'
从引用名称中删除远程名称(origin/somebranch变为somebranch):
sed 's/.*\///'
使用xargs调用单线:
xargs git push --delete origin
把所有这些都放在一起,你会得到:
git branch -r --merged | sed '/develop\|master\|HEAD\|upstream/d' | sed 's/.*\///' | xargs git push --delete origin
这将使我只剩下一些我曾经工作过但尚未合并的分支。然后,您可以逐个删除它们,因为它们不应该太多。
查找不再需要的分支:
git branch -ar
假设找到要删除的branch1、branch2和branch3:
git push --delete origin branch1 branch2 branch3
我的Bash脚本贡献大致基于mmrobin的答案。
它需要一些有用的参数来指定include和exclude,或者只检查/删除本地或远程分支,而不是两者。
#!/bin/bash
# exclude branches regex, configure as "(branch1|branch2|etc)$"
excludes_default="(master|next|ag/doc-updates)$"
excludes="__NOTHING__"
includes=
merged="--merged"
local=1
remote=1
while [ $# -gt 0 ]; do
case "$1" in
-i) shift; includes="$includes $1" ;;
-e) shift; excludes="$1" ;;
--no-local) local=0 ;;
--no-remote) remote=0 ;;
--all) merged= ;;
*) echo "Unknown argument $1"; exit 1 ;;
esac
shift # next option
done
if [ "$includes" == "" ]; then
includes=".*"
else
includes="($(echo $includes | sed -e 's/ /|/g'))"
fi
current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
if [ "$current_branch" != "master" ]; then
echo "WARNING: You are on branch $current_branch, NOT master."
fi
echo -e "Fetching branches...\n"
git remote update --prune
remote_branches=$(git branch -r $merged | grep -v "/$current_branch$" | grep -v -E "$excludes" | grep -v -E "$excludes_default" | grep -E "$includes")
local_branches=$(git branch $merged | grep -v "$current_branch$" | grep -v -E "$excludes" | grep -v -E "$excludes_default" | grep -E "$includes")
if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
echo "No existing branches have been merged into $current_branch."
else
echo "This will remove the following branches:"
if [ "$remote" == 1 -a -n "$remote_branches" ]; then
echo "$remote_branches"
fi
if [ "$local" == 1 -a -n "$local_branches" ]; then
echo "$local_branches"
fi
read -p "Continue? (y/n): " -n 1 choice
echo
if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
if [ "$remote" == 1 ]; then
remotes=$(git remote)
# Remove remote branches
for remote in $remotes
do
branches=$(echo "$remote_branches" | grep "$remote/" | sed "s/$remote\/\(.*\)/:\1 /g" | tr -d '\n')
git push $remote $branches
done
fi
if [ "$local" == 1 ]; then
# Remove local branches
locals=$(echo "$local_branches" | sed 's/origin\///g' | tr -d '\n')
if [ -z "$locals" ]; then
echo "No branches removed."
else
git branch -d $(echo "$locals" | tr -d '\n')
fi
fi
fi
fi
Git Sweep在这方面做得很好。
刚刚为此创建了python脚本:
import sys
from shutil import which
import logging
from subprocess import check_output, call
logger = logging.getLogger(__name__)
if __name__ == '__main__':
if which("git") is None:
logger.error("git is not found!")
sys.exit(-1)
branches = check_output("git branch -r --merged".split()).strip().decode("utf8").splitlines()
current = check_output("git branch --show-current".split()).strip().decode("utf8")
blacklist = ["master", current]
for b in branches:
b = b.split("/")[-1]
if b in blacklist:
continue
else:
if input(f"Do you want to delete branch: '{b}' [y/n]\n").lower() == "y":
call(f"git branch -D {b}".split())
call(f"git push --delete origin {b}".split())
您需要从这些命令中排除master、main和develop分支。
本地git清除:
git branch --merged | grep -v '\*\|master\|main\|develop' | xargs -n 1 git branch -d
远程清零:
git branch -r --merged | grep -v '\*\|master\|main\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin
同步远程分支的本地注册表:
git fetch -p
推荐文章
- 为什么我需要显式地推一个新分支?
- 如何撤消最后的git添加?
- Rubymine:如何让Git忽略Rubymine创建的.idea文件
- Gitignore二进制文件,没有扩展名
- Git隐藏错误:Git隐藏弹出并最终与合并冲突
- 了解Git和GitHub的基础知识
- 没有。Git目录的Git克隆
- Git与Mercurial仓库的互操作性
- 忽略git中修改(但未提交)的文件?
- “git restore”命令是什么?“git restore”和“git reset”之间有什么区别?
- Git合并与强制覆盖
- Git拉另一个分支
- 在Bash命令提示符上添加git分支
- 如何更改Git日志日期格式
- git pull -rebase和git pull -ff-only之间的区别