列出并删除git分支而不进行克隆

列出并删除git分支而不进行克隆,git,branch,Git,Branch,我有一个git项目列表,我想清理其中的旧分支,我想做的是列出并删除合并到master的所有分支 有没有一种方法可以在不在本地克隆每个回购协议的情况下执行上述操作?您需要git ls remote: 名字 git ls remote-列出远程存储库中的引用 概要 for k in $(git branch -r --merged origin/master | cut -d" " -f 3); do echo $k done 要仅获取分支(头),需要缩小参照规范的范围: % git ls

我有一个git项目列表,我想清理其中的旧分支,我想做的是列出并删除合并到master的所有分支


有没有一种方法可以在不在本地克隆每个回购协议的情况下执行上述操作?

您需要
git ls remote

名字

git ls remote
-列出远程存储库中的引用

概要

for k in $(git branch -r --merged origin/master | cut -d" " -f 3); do
    echo $k
done
要仅获取分支(头),需要缩小参照规范的范围:

% 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
现在您可以围绕此输出编写脚本,如

% 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
请注意,我们正在使用
printf
shell内置命令来限定我们用ASCII NUL字符输出的引用的名称,然后将
-0
传递给
xargs
以期望NUL终止的输入。 这样,我们就可以处理时髦的引用名称(包含空格等)

一些解释:

  • 如果
    git cat file-t
    未能找到对象 使用本地存储库中指定的SHA1名称, 它以非零退出代码退出并打印

    致命:git cat文件:无法获取对象信息

    到它的标准

  • 因此,要测试远程参考点所在的历史记录是否存在于本地 我们在对象的SHA1名称上运行
    git cat file-t
    指向,获取该命令的组合输出,然后进行测试 是否使用非零退出代码(
    $?-ne 0
    )退出,以及 其错误消息是否指示缺少对象 (
    ${VAR#PATTERN}
    从内容中删除与
    PATTERN
    匹配的前缀 并返回结果值)

  • 如果远程引用点所在的历史记录在本地存储库中不存在,则无法根据定义将其合并到任何本地引用, 因此,如果我们检测到这样一个ref,我们将跳过它的进一步测试
    git分支--合并


拥有更多git知识的人可能能够对此进行扩展,但今天我遇到了类似的挑战,我想在多个回购中删除一个分支,但我不想在删除分支之前克隆每个分支

事实证明,git可以让您在不同的回购协议中删除分支,只要您在某个回购协议中。我不确定这里是否有任何限制,比如必须指向同一个GitHub服务器等等

但这对我起了作用:

#!/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
如果你仔细想想,这与:

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 branch
和用
git branch-d
替换delete。我将使用'git branch-d branch_name'删除分支yes,我想知道的是,是否有一种方法可以做到这一点,而不需要存储库的本地副本。这可能是我没有正确解释的,但我需要的是一种方法,可以列出合并到master的分支(如OP中的代码),而不需要存储库的本地副本。这正是我需要的,我以前见过ls遥控器,但不懂它。谢谢这里有一个大问题:除非您的存储库是最新的,否则,
git分支--merged
无法给您正确的答案。这意味着您最好先运行
git fetch
,然后在本地工作。@torek,没错。另一方面,这个问题是为了避免下载历史(我认为“不克隆”也意味着“不获取”)。一种解决方法是测试“不在存储库中提交”的特殊情况。不幸的是,在
git分支{--contains |--merged}
中处理这种情况(对我来说)是令人惊讶的:因为他们假设具有给定名称的对象确实存在,如果不存在,就会发出一条没有多大帮助的错误消息。假定首先在提交名称上运行
git cat file-t“$sha”
会更好,因为它的行为在我看来更可预测。@torek,作为推论,如果
git cat file-t“$sha”
出错(在这里,git 2.11.1中,它说“无法获取对象信息”,并以代码128退出),这意味着,
$sha
标识的ref没有被合并,因此不能从远程存储库中删除。我认为这现在很好。关于分支名称被粗暴地移动到不相交的子图,仍然有一些极端情况(OP实际上并没有询问),但这些可能应该被视为“未合并”,这样就可以了。
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