修复或撤消标签上的分离头

时间:2021-07-09 14:16:08

标签: git github

嘿,我真的可以用一些帮助来解决我的情况,

我创建了一个空的 repo 并为其添加了一个标签,并在 Zenodo 中指向该 repo 以进行 doi 创建 后来我将某些文件推送到 repo 我真的不知道我是怎么搞砸的 但我想我可能已经将标签合并到 main 我不再有标签了 当我克隆它时,我收到的第一条消息是

git clone --depth 1 --branch v1.0 repourl
Unpacking objects: 100% (3/3), done.
Note: checking out 'xxx'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
  git checkout -b <new-branch-name>

有什么方法可以解决这个问题对我来说在标签中有文件真的很重要 我可以在网上看到标签,zenodo 也是 唯一的问题是那里没有文件,但是可以在主分支中找到它们。 由于我无法更改 zenodo 链接,有什么办法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

TL;DR

这里没有什么可以解决的,至少在您提出的问题中是这样。

长(ish)

您发布的输出不包含错误或错误。但是,您的问题充满了不正确的假设和陈述。 Git 对初学者来说是出了名的难(或对他们不友好),你已经接触到了它的几个经典项目。

第一:文件不存储在标签中。事实上,Git 一开始并不存储文件。 Git 存储的是提交。在很大程度上,Git 存储库只是提交的大集合。所以这应该立即给你留下一个问题:究竟什么是提交?

有些细节尚不重要,因此我们将跳过它们。最重要的两个是:

  • 每个提交都有编号。然而,这些数字并不是简单的计数:它们不会“提交 #1”,然后是“提交 #2”,然后是 #3,依此类推。相反,每个数字都是独一无二的,但巨大且看起来随机。它用 hexadecimal 表示,看起来像 d486ca60a51c9cb1fe068803c3f540724e95e83a。这个数字是 Git 在存储库中实际找到提交的方式。但人类通常不会直接处理数字:它们太大太丑,无法正确输入。

  • 每次提交都保存每个文件的完整快照。这就是 Git 保存文件的方式,即使它没有将它们存储为文件。 Git 存储提交,然后提交将文件存储为一种存档,如 tarball 或 zip 存档或 RAR 或其他。

为了找到存储库中的提交,Git 给了我们几种名称。两个最重要的是分支名称标签名称这两种名称都只存储一个原始提交哈希 ID。这意味着当您使用该名称时,您将获得该特定提交。在这里,分支名称和标记名称之间的主要区别在于分支名称在不同时间选择不同的提交。更准确地说,分支名称 命名在该分支“上”的最新 提交。稍后提交,分支名称将——必须——改变。但是,标签名称会永远命名一个特定的提交

考虑到这一点:

<块引用>

我创建了一个空仓库

到目前为止,一切正常。一个空的存储库是一个没有提交的存储库。由于它没有提交,它不能有任何分支或标签名称:分支或标签名称​​必须包含该存储库中存在的某个提交的哈希 ID。1

请注意,当 GitHub 为您创建新存储库时,他们会(可选)将一个初始提交放入新存储库,以便分支和标记名称可以存在。这会在 GitHub 上创建初始分支名称 - 以前是 master,但现在是 main

<块引用>

并为其添加标签

这部分是不可能的。必须至少有一次提交。

<块引用>

后来我将某些文件推送到仓库

您所做的是创建一个或多个提交。这允许分支和标签名称出现。然后你为其中一个提交创建了一个标签名称。您添加的每个提交也包含一些文件集,作为这些特定文件的特定版本的永久存档。

您现在拥有并且可能仍然拥有一个带有一些分支名称(例如 master 和/或 main)和至少一个标记名称(特别是 v1.0)的存储库。您还使用 git push 将新提交、任何分支名称更新以及新分支和标签名称发送到 GitHub 上的存储库副本。这些是存储库的独立副本,因此它们可能会不同步,而且——这部分非常重要——每个副本都有自己的分支名称。这两个副本share标签名,和share commits,但它们都有自己的分支名

<块引用>

...我想我可能已经将标签合并到 main

Git 的 git merge 是另一个相当复杂的主题,但您不必在这里担心 标签。合并操作合并提交。标签一旦制作完成,就留在原地。2

<块引用>

当我克隆 [存储库,Git 说]

... You are in 'detached HEAD' state ...

这是因为您告诉 git clone 您要使用的名称是 v1.0

<块引用>
git clone ... --branch v1.0 ...

git clone 的工作方式是:

  1. 它会创建一个新的空目录。3然后在新目录中完成剩余的操作。
  2. 它会创建一个新的空存储库(实际上是通过运行 git init)。
  3. 它向这个存储库添加了一个 remotegit remote add origin url,或多或少)。这是一个短名称,您的 Git 可以通过它联系另一个 Git,您将要从中复制所有提交。
  4. 它会运行您要求它执行的任何其他 git config 操作(您没有执行,因此此处的第 4 步不会执行任何操作)。
  5. 它或多或少地运行 git fetch origin。这通常从另一个 Git 复制所有提交,但不复制任何分支。但是,您确实可以获得他们所有的标签。但是,在使用 --depth 1 时,您不会获得所有提交、所有标签或所有分支。4
  6. 最后,从另一个 Git 获得所有(或几个,或一个)提交后,您的 Git 使用您提供给 --branch 的参数来选择要在您自己的 Git 存储库中创建的分支。如果您没有使用--branch,您的 Git 会询问他们的 Git 他们推荐哪个分支名称。不过,这里有一个奇怪的标签特殊情况。

由于您确实同时使用了 --depth (1) 和 --branch(带有标签名称),因此您会得到两种特殊情况:

  • 您的 Git 进行了 Git 所谓的单分支克隆,即,无需费心从您没有特别要求。

  • 而且,由于您对 --branch 的参数是 tag 名称而不是 branch 名称,因此您实际上 在全部来自他们。您只需复制由一个标签名称指定的一次提交。然后,您的 Git 完全没有创建分支名称,并检查该提交,正如 Git 所说的分离的 HEAD

由于您使用了 --depth 标志而不使用 --no-single-branch 标志,因此您获得了单分支克隆;由于您选择的分支并不是真正的分支,因此您获得了一个 no-branch 克隆。这种克隆使用起来非常混乱。它的主要用途是进行单个构建,例如,作为发布构建。不太适合做实际工作。

一般来说,那些刚接触 Git 的人应该避免使用单分支克隆,避免使用 --depth 参数,并且在使用 {{1} 时只将 分支名称 传递给 --branch }. (从某种意义上说,最好使用 git clone 而没有 git clone 选项,而是为 --branch 提供 -n 选项,这使得它跳过步骤6 完全。但是,您必须首先自己做 git clonegit checkout,这不是最方便的开始方式,即使它只是一个额外的步骤。)


1从技术上讲,标签名称可以包含提交以外的其他东西的哈希 ID——但通常,标签命名一个特定的提交,即使它是间接的。我包含此脚注只是为了在技术上正确 (the best kind of correct)。

2从技术上讲,如果您强制移动标签,则可以移动标签,并且在某些情况下,非常旧的 Git 版本(早于 1.8.2)不小心将分支名称规则应用于标签名称。这很早以前就修复了,但有些系统仍然带有 Git 1.7 (!)。如果您使用的是这样一个古老的系统,您应该尽可能升级。 GitHub 正在使用更现代的 Git(实际上,GitHub 有时会推动一些更新 Git),因此他们至少没有这个标签问题。

3您可以告诉 git switch 接管现有的空目录,但这种情况不太常见 - 没有太多理由这样做 - 这不是您在这里所做的.

4这里的细节异常复杂,尽管有充分的理由。去掉 git clone,你获得所有提交——好吧,其他 Git 愿意交出的所有提交,在使用 GitHub 时对某些拉取请求相关项目取模——以及所有标签,即使使用 --depth 1 参数。将 --branch 添加到 --no-single-branch,您将获得他们所有的分支提示提交,也许还有更多标签。这就是一切变得复杂的原因。