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

A.J*_*Jac 10 git branch

for k in $(git branch -r --merged origin/master | cut -d" " -f 3); do
    echo $k
done
Run Code Online (Sandbox Code Playgroud)

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

有没有办法在不在本地克隆每个回购的情况下执行上述操作?

kos*_*tix 16

你需要git ls-remote:

名称

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

概要

git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]
              [-q | --quiet] [--exit-code] [--get-url]
              [--symref] [<repository> [<refs>...]]
Run Code Online (Sandbox Code Playgroud)

描述

显示远程存储库中可用的引用以及关联的提交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
Run Code Online (Sandbox Code Playgroud)

要获得只有分支(头),您需要缩小refspec:

% git ls-remote origin 'refs/heads/*'
6a60cc68a2953f1a62b0dca641eb29509b5b6e8c        refs/heads/expdate-fix
af51dfb080728117d898e1d0a10e3fe01ed67063        refs/heads/master
4c42e43b4ccfd37074d115f6e9a694ddb8b70d55        refs/heads/redux
fd18a67bbc5cbf8aa6cda136afa4e5c20ed2d522        refs/heads/rest
Run Code Online (Sandbox Code Playgroud)

现在你可以像这样输出脚本

git ls-remote origin 'refs/heads/*' | while read sha ref; do
  # test if $sha is merged
done
Run Code Online (Sandbox Code Playgroud)

要删除分支,您需要"不做任何事",就像在

git push origin :refs/heads/feature-x
Run Code Online (Sandbox Code Playgroud)

(注意":"左边的空字符串,它定义了推送到右侧的内容).

所以我们得到类似的东西

#!/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
Run Code Online (Sandbox Code Playgroud)

请注意,我们使用printfshell内建界定与ASCII字符NUL裁判,我们输出的名称,然后传递-0xargs期望NUL结束的输入.这样我们就可以解决时髦的引用名称(包含空格等).

一些解释:

  • 如果git cat-file -t <object_sha1_name>无法在本地存储库中找到具有指示的SHA1名称的对象,则它将以非零退出代码退出并打印

    致命:git cat-file:无法获取对象信息

    对它的stderr.

  • 因此,为了测试远程ref的历史记录是否存在于本地存储库中,我们git cat-file -t在它指向的对象的SHA1名称上运行,获取该命令的组合输出,然后测试它是否以非零退出代码退出($? -ne 0并且它的错误消息是否表示缺少对象(从变量的内容中${VAR#PATTERN}删除前缀匹配并返回结果值).PATTERNVAR

  • 如果远程ref指向的历史记录在本地存储库中不存在,则根据定义它不能合并到任何本地引用,因此如果我们检测到这样的引用,我们将跳过其进一步测试 git branch --merged.