检查Git上的标签

时间:2017-07-04 10:14:40

标签: git git-tag

我正在浏览一些git内部,并且看到了标签以及它们如何在内部存储。在Git SCM site我找到了以下内容:

  

签出标签

     

你无法真正签出Git中的标签,因为它们无法移动   周围。如果你想在你的版本中放置一个版本的存储库   工作目录看起来像一个特定的标签,你可以创建一个新的   使用git checkout -b [branchname] [tagname]分支到特定标签:

     

git checkout -b version2 v2.0.0

     

切换到新分支'版本2'

     

当然,如果你这样做并提交,你的version2分支将是   与v2.0.0标签略有不同,因为它会向前移动   随着你的新变化,所以要小心。

我有以下疑问:

  1. 为什么我们无法查看代码?我们不能遍历Git TAG以使HEAD指向标记指向的提交吗?
  2. 我们可以创建一个新的提交,然后指向提交 标签指向父母?
  3. 据说如果我们从标签创建一个新的分支并提交,它会略有不同。他们在谈论什么不同?赢得新提交(假设没有任何改变)将标记的提交称为其父级,其他所有内容(树和blob)保持不变?
  4. 谢谢。

    修改
    我指的是HEAD和标签指向不同提交的情况。

1 个答案:

答案 0 :(得分:4)

  

为什么我们不能查看标签?

我们可以!

  

我们不能遍历Git TAG以使HEAD指向标记所指向的提交吗?

是的,我们可以做到这一点(但严格来说,我们甚至不需要太多,如果有任何遍历:提交是快照,所以一旦我们到达正确的,我们就完成了,标签通常需要零或达到提交的一个中间步骤。)

HEAD文件的更典型状态 - 它是名为.git的{​​{1}}中的实际文件 - 是它包含分支的名称 ,而不是提交的 ID 。这种模式没有太多的正式名称,但我将其称为“在分支上”,将其与其他模式进行对比。

HEAD直接指向某个提交(通过包含其哈希ID)时获得的模式是as CodeWizard mentioned in a comment,称为“分离的HEAD”。由于.git/HEAD不再包含分支的名称,因此我们现在位于 no 分支上 - 或者等效地,在某种未命名的分支上,我们可以使用.git/HEAD用于命名的符号(自Git版本1.8.5开始),或拼写出单词@。当然HEAD是个好名字;只是当我们再次运行HEAD时,Git将覆盖.git/HEAD文件的内容,然后我们将不再将哈希ID存储在任何地方。

  

我们可以创建一个新的提交,然后指向tag指向的提交作为父提交吗?

英语在这里有点含糊不清,但我认为图表更清楚答案是肯定的:

git checkout master

此处,提交 initially: on branch `master` with commit `H` as the current commit ...--F--G <-- tag: v2.0.0 \ H <-- master (HEAD) 指回提交H;提交G指向提交G;等等。名为F的分支指向提交master,标记名H指向提交v2.0.0(直接,如果它是轻量级标记,或通过一个带注释的标签对象,如果它是带注释的标签)。

G

After `git checkout v2.0.0`: ...--F--G <-- HEAD, tag: v2.0.0 \ H <-- master 文件现在包含提交.git/HEAD的哈希ID。

G

新提交If we make a new commit now: I <-- HEAD / ...--F--G <-- tag: v2.0.0 \ H <-- master 已提交I作为其父级,如您所建议的那样。 G文件现在包含提交.git/HEAD的哈希ID。

  

据说如果我们从标签创建一个新的分支并提交,它会略有不同。他们在谈论什么不同?新的提交(假设没有任何改变)是否会将标记的提交称为其父级,其他所有内容(树和blob)保持不变?

提交内容将是相同的,但提交图的绘图会稍微改变一下。这是新的图形绘制,从相同的起点开始,但使用I作为中间步骤。

git checkout -b version2 v2.0.0

请注意,在这种情况下 - 我们在“分支”上的一个名为 initially: on branch `master` with commit `H` as the current commit ...--F--G <-- tag: v2.0.0 \ H <-- master (HEAD) After `git checkout -b version2 v2.0.0`: ...--F--G <-- version2 (HEAD), tag: v2.0.0 \ H <-- master If we make a new commit now: I <-- version2 (HEAD) / ...--F--G <-- tag: v2.0.0 \ H <-- master - 的分支名称随着我们进行新提交而移动 。当我们不在任何分支上时,在“分离的HEAD”模式下,新提交只更新(存储在其中的提交哈希ID)version2。但是当.git/HEAD包含分支的名称时,那些新提交会更新该分支.git/HEAD文件本身只是继续包含分支的名称。

事实上,这就是“在一个分支上”意味着什么:只要.git/HEAD包含分支的名称,各种操作 - 特别包括进行新的提交和使用.git/HEAD - 更改分支名称记住的哈希ID ,而不是更改git reset本身。只要.git/HEAD包含提交的哈希ID ,这些相同的操作就会更新.git/HEAD本身。

.git/HEAD命令通常会更新git checkout的内容,并且是可以更改.git/HEAD中存储的分支名称的少数命令之一。 (我在这里说“通常”,因为.git/HEAD有点kitchen-sink command,有各种模式做奇怪的事情,因为它们与它通常做的主要事情密切相关。)具体来说,如果你在一个分支上,git checkout可以把你带到不同的分支;如果你不在任何一个分支上,git checkout可以让你进入一个分支;如果您使用git checkout或标签名称或类似名称,--detach可以使您进入分离的HEAD模式;如果您不在任何分支上,git checkout可以更改指向哪个提交git checkout

HEAD命令可以执行其中的一些操作,但它不会带你上下任何分支。就像git reset一样,它有点“厨房下沉”:它有很多东西它可以做到,如果没有很多单词和几个图表,很难很好地描述这些!)