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

时间:2017-01-31 11:47:25

标签: git branch

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

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

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

2 个答案:

答案 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

除非您要使用显式路径替换参考原点