for k in $(git branch -r --merged origin/master | cut -d" " -f 3); do
echo $k
done
我有一个我希望清理旧分支的git项目列表,我想要做的是列出并删除所有合并到master的分支。
有没有办法在不在本地克隆每个仓库的情况下执行上述操作?
答案 0 :(得分:14)
您需要git ls-remote
:
NAME
git-ls-remote
- 列出远程存储库中的引用概要
git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>] [-q | --quiet] [--exit-code] [--get-url] [--symref] [<repository> [<refs>...]]
说明
显示远程存储库中可用的引用以及 关联的提交ID。
所以它的工作原理如下:
% git ls-remote origin
af51dfb080728117d898e1d0a10e3fe01ed67063 HEAD
6a60cc68a2953f1a62b0dca641eb29509b5b6e8c refs/heads/expdate-fix
af51dfb080728117d898e1d0a10e3fe01ed67063 refs/heads/master
4c42e43b4ccfd37074d115f6e9a694ddb8b70d55 refs/heads/redux
fd18a67bbc5cbf8aa6cda136afa4e5c20ed2d522 refs/heads/rest
7ad17cdf8b0dcd1a29a1795a363279fb3c76ac66 refs/tags/test.key
be0b2d6881902600fb3d6686c10d0a47f1e6751a refs/tags/test.pub
要获得分支(头部),您需要缩小refspec:
% git ls-remote origin 'refs/heads/*'
6a60cc68a2953f1a62b0dca641eb29509b5b6e8c refs/heads/expdate-fix
af51dfb080728117d898e1d0a10e3fe01ed67063 refs/heads/master
4c42e43b4ccfd37074d115f6e9a694ddb8b70d55 refs/heads/redux
fd18a67bbc5cbf8aa6cda136afa4e5c20ed2d522 refs/heads/rest
现在您可以编写此输出的脚本,如
git ls-remote origin 'refs/heads/*' | while read sha ref; do
# test if $sha is merged
done
要删除分支,您需要“不做任何事”,就像在
中一样git push origin :refs/heads/feature-x
(注意“:”左边的一个空字符串,它定义了推送到右侧的内容)。
所以我们得到像
这样的东西#!/bin/sh
set -e -u
git ls-remote origin 'refs/heads/*' | while read sha ref; do
# test if $sha is merged
E=`git cat-file -t "$sha" 2>&1`
test $? -ne 0 -a "${E#*git cat-file: *}" = "could not get object info" && continue
git branch --merged "$sha" && printf ':%s\0' "$ref"
done | xargs -0 git push origin
请注意,我们使用printf
shell内置来界定我们使用ASCII NUL字符输出的引号的名称,然后将-0
传递给xargs
以期望NUL终止输入。
这样我们就可以解决时髦的引用名称(包含空格等)。
一些解释:
如果git cat-file -t <object_sha1_name>
无法找到该对象
使用本地存储库中指示的SHA1名称,
它以非零退出代码退出并打印
致命:git cat-file:无法获取对象信息
到它的stderr。
因此要测试远程ref的历史记录是否存在于本地
存储库我们在对象的SHA1名称上运行git cat-file -t
指向,抓取该命令的组合输出然后测试
是否退出时使用非零退出代码($? -ne 0
)和
它的错误消息是否表示缺少对象
(${VAR#PATTERN}
从内容中删除匹配PATTERN
的前缀
变量VAR
并返回结果值。
如果远程ref指向的历史记录在本地存储库中不存在,则根据定义,它不能合并到任何本地引用,
因此,如果我们检测到这样的参考,我们会跳过进一步的测试
git branch --merged
。
答案 1 :(得分:0)
拥有更多git知识的人也许可以对此进行扩展,但是今天我遇到了类似的挑战,因为我想在多个存储库中删除一个分支,但是我不想在删除该分支之前克隆每个分支。 / p>
事实证明,只要您在某个存储库中,git即可让您删除其他存储库中的分支。我不确定这里是否有任何限制,例如它们必须指向相同的GitHub服务器等。
但这对我有用:
cd to a repo dir you do not want to remove
git push git@server:path_to_repo.git :branch_you_want_to_delete
考虑一下,这与以下内容相同:
git push origin :branch_you_want_delete
除非您要使用显式路径替换参考原点