git 离线检查 git 标签是否已经推送到远程?

git offline check if git tag was already pushed to remote?

我能问一下 git 上次 git 在没有在线连接的情况下检查 git 遥控器上的哪些标签吗?

git 是否跟踪它已将标签推送到哪些遥控器?

使用 git 分支可以使用 git diff --stat branch-name remote-name/branch-name。如果远程分支不存在,git diff 将通过显示错误和非零退出代码来指出这一点。

git ls-remote origin tag 做我想做的,但它需要我想避免的在线连接。

我希望工作的是 git diff --stat tag-name remote-name/tag-name,但似乎本地标签无法通过这种方式轻松地与远程标签进行比较。

目的:有很多 git 个存储库,自动化,脚本化,检查哪些标签已经被推送,避免不必要的缓慢的互联网连接,避免遇到速率限制。

Can I ask git what it thinks which tags are on a git remote last time git checked without an online connection?

并非没有提前准备。通过适当的高级准备,是的。

Does git keep track on to which remotes it already pushed tags?

没有

这里有几个技术问题:

  • 您使用 git push 实际推动的是 提交
  • 但在 git push 的最后,您还要求其他 Git 软件在 中创建、删除或更新某些 names =]它的存储库.

标签名称只是以魔术序列 refs/tags/ 开头的名称(“refs”);名称的其余部分是标签名称。但是,标签名称在 Git 中具有特殊地位,类似于分支和 remote-tracking 名称具有特殊地位的方式:

  • A branch 名称(以 refs/heads/ 开头的名称)被限制为仅指向提交,从不指向任何其他对象。当分支名称通过 git fetch 传输时,它通常 1 变成 remote-tracking 名称 ,即名称开头使用 refs/remotes/ 并包括遥控器的名称和另一个斜杠。

  • 一个标签名在某些条件下是auto-fetched。

  • git push操作变成了一种操作,在接收端,默认强制执行一些检查:

    • 分支名称必须以 fast-forward 方式移动;和

    • 标签名称不能移动

    (除了Git1.8.2之前的版本,Git不小心在这里用了标签名的分支规则)

  • 本地存储库通过 remote-name 对远程存储库执行 git push 将在成功状态下更新其 remote-tracking 名称:即推送从您的笔记本电脑到 GitHub,如果 main 成功,您的笔记本电脑会更新您的 origin/main remote-tracking 名称。

所以我们在这里看到分支名称应用了各种特殊的怪异,带有这个 remote-tracking 名称的东西。这使 branch 名称特定于任何一个给定的存储库。我的分支名称,在我克隆的一些 GitHub 存储库中,是 我的,你的是 你的,我们使用 Git要同步的集线器。

标签 名称没有那么奇怪(标签名称通常指向标签对象而不是提交对象),但标签名称通常被认为是一个通用替代品特定的提交哈希 ID:如果我在提交 a123456 时创建标签 v1.2 并推送到 GitHub 上的共享存储库,GitHub 接受此当且仅当 v1.2 对他们来说是全新的,从现在到永远,每个人都同意 v1.2 只是 a123456 的 human-readable 名称。人们使用 v1.2,Git 使用 a123456,我们总是在谈论相同的提交。

因为标签只会被创建,永远不会移动,如果你有标签 v1.2,我有标签 v1.2,在一些正在进行共享的存储库上,这些最好指的是完全相同的提交哈希 ID,因此无需同步我们的 v1.2 标签。

当然,只有当我们可以从我的存储库到您的存储库或共享的第三个存储库(例如,在 GitHub 上)在线交谈时,所有同步才会发生。所以我完全有可能在你为不同的提交v1.2创建v1.2的同时意外创建一个v1.2 =144=]。 Git 只是假设这不会发生。如果它真的发生了,你几乎只能靠自己了。

了解了所有这些,我们现在可以通过注意以下几点来解决您真正的潜在问题:

  • git pushgit fetch 通过 refspecs.
  • 传输引用
  • refspecs 允许创建 maps。这就是 remote-tracking 名称的工作原理。

当我从 origin 获取时, 默认 refspec 是 +refs/heads/*:refs/remotes/origin/*。这就是 remote-tracking 名称出现在我的存储库中的原因。如果我添加 --tags,Git 添加 refs/tags/*:refs/tags/*。这就是导致标签 not 具有 remote-tracking 等价物的原因。 (特别奇怪的是,如果没有 explicit --no-tags,如果我获取提交 b789abc 并且该提交被标记为 v2.2 我的 Git也会创建refs/tags/v2.2。此特殊代码在Git 多年来经历了多次修改,并存在一定程度的Git 版本漂移,但主要效果非常一致。)

您可以做的高级准备是 添加到您的默认提取 refspecs 以便 git fetch origin 将 force-update refs/rtags/origin/* 或其他一些相似 name-space 基于 origin 上找到的 refs/tags/* 个名字。不会有任何神奇的 push-like 机会更新,但 git fetch 会选择这些。

要做到这一点,您只需添加:

fetch = +refs/tags/*:refs/rtags/origin/*

origin 遥控器的 git config 行;然后 git fetch origin 将更新您的 remote-tag-tracking-names.

Purpose: With a lot of git repositories, automated, scripted, checking which tags have already been pushed ...

以上可能有效,但使用一些脚本来跟踪列表 o 可能更简单远程 and/or 您已从自动脚本中成功 运行 git push <remote> <tag> 的网址。您可以使用 git config 将这些存储在 .git/config 中。您选择格式;使用能让你自己轻松工作的东西。如果某个遥控器没有列出某个标签,你可以 运行 git push 给它,或者 git ls-remote 给它,尝试推送标签 and/or 来检查,然后使用 git config 更新状态以更新 .git/config 文件。

(您也不必将其存储在 .git/config 中,如果您同时在做其他 Git 事情,您可能需要使用 git config --file $GIT_DIR/tag-tracking ,例如,这样您就不会 运行 进入锁争用。)


1请注意 镜像克隆 具有不同的默认 refspec,因此没有 remote-tracking 名称。