git - 在 Git 上 check out 标签

标签 git git-tag

我正在浏览一些 git 内部结构并遇到标签以及它们如何在内部存储。在 Git SCM site 中,我发现了以下内容:

Checking out Tags

You can’t really checkout a tag in Git, since they can’t be moved around. If you want to put a version of your repository in your working directory that looks like a specific tag, you can create a new branch at a specific tag with git checkout -b [branchname] [tagname]:

git checkout -b version2 v2.0.0

Switched to a new branch 'version2'

Of course if you do this and do a commit, your version2 branch will be slightly different than your v2.0.0 tag since it will move forward with your new changes, so do be careful.



我有以下疑问:
  • 为什么我们不能 check out 标签?难道我们不能遍历Git TAG,让HEAD 指向tag 指向的提交吗?
  • 我们可以创建一个新的提交然后指向提交吗
    由标记指向父项?
  • 据说如果我们从标签创建一个新的分支并提交,它会略有不同。他们说的有什么区别?新提交(假设没有任何变化)不会将标记提交作为其父提交,而其他所有内容(树和 blob)都保持不变吗?

  • 谢谢你。

    编辑:
    我指的是 HEAD 和标签指向不同提交的情况。

    最佳答案

    Why can't we check out tags?



    我们可以!

    Can't we traverse the Git TAG to make HEAD point to the commit pointed to by the tag?



    是的,我们可以做到这一点(不过,严格地说,如果有任何遍历,我们甚至不需要太多:提交是快照,因此一旦我们到达正确的位置,我们就完成了,并且标签通常需要零个或一个中间步骤到达提交)。
    HEAD 文件(它是 .git 中名为 HEAD 的实际文件)的更典型状态是它包含分支的名称,而不是提交的 ID。这种模式没有太多正式的名称,但我称之为“在分支上”,以与其他模式进行对比。

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

    Can we create a new commit which will then point to the commit pointed to by tag as the parent?



    英语在这里有点模棱两可,但我认为一张图更清楚地表明答案是"is":
     initially: on branch `master` with commit `H` as the current commit
    
     ...--F--G     <-- tag: v2.0.0
              \
               H   <-- master (HEAD)
    

    这里,commit H 指向commit 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 文件现在包含提交 G 的哈希 ID。
    If we make a new commit now:
    
               I   <-- HEAD
              /
     ...--F--G     <-- tag: v2.0.0
              \
               H   <-- master
    

    正如您所建议的,新提交 I 已提交 G 作为其父项。 .git/HEAD 文件现在包含提交 I 的哈希 ID。

    It is said that if we create a new branch from the tag and commit, it'll be slightly different. What difference are they talking about? Won't the new commit (assuming nothing has changed) refer to the tagged commit as its parent with everything else (trees & blobs) remaining the same?



    提交内容将是相同的,但提交图的绘制会有所改变。这是新的图形绘制,从相同的起点开始,但使用 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
    

    请注意,在这种情况下 - 我们在名为 version2 的“分支上” - 分支名称随着我们进行新的提交而移动 。当我们不在任何分支上时,在“分离的 HEAD”模式下,新提交只会更新(存储在其中的提交哈希 ID) .git/HEAD 。但是当 .git/HEAD 包含分支的名称时,这些新提交会更新该分支。 .git/HEAD 文件本身只是继续包含分支的名称。

    事实上,这就是“在分支上”的含义:每当 .git/HEAD 包含分支名称时,各种操作——特别是包括进行新提交和使用 git reset——更改分支名称记住的哈希 ID,而不是更改.git/HEAD 本身。每当 .git/HEAD 包含提交的哈希 ID 时,这些相同的操作只会更新 .git/HEAD 本身。
    git checkout 命令通常更新 .git/HEAD 的内容,是少数可以更改 .git/HEAD 中存储的分支名称的命令之一。 (我在这里说“通常”是因为 git checkout 有点像 kitchen-sink command ,有各种模式可以做奇怪的事情,只是因为它们与它通常做的主要事情密切相关。)具体来说,如果你在一个分支上,git checkout 可以把你放在一个不同的分支上;如果您不在任何分支上,git checkout 可以让您进入一个分支;如果您使用 --detach 或标签名称或类似名称,git checkout 可以让您进入分离的 HEAD 模式;如果您不在任何分支上,git checkout 可以更改 HEAD 指向的提交。

    (git reset 命令可以做一些这样的事情,但它不会带你进入或离开任何分支。像 git checkout 一样,它有点“厨房下沉”:它可以做很多事情,很难很好地描述这些没有太多的文字和几个图表!)

    关于git - 在 Git 上 check out 标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44903176/

    相关文章:

    git - 如何验证git中每个提交的作者

    github - 使用 GitHub Actions 创建标签而不是发布

    git - 如何列出所有的 Git 标签?

    git - 添加标签/标签到 git 提交

    git - 在 GitLab 上,如何比较两个不同提交的文件

    git - 相当于 IntelliJ IDEA "VCS → Update Project"和 Git 的命令行

    git - 使用公钥/私钥推送到 TFS git

    git - 有没有办法在 git 恢复之前取回已提交的更改?

    git - git rebase没有应用提交

    git - 为什么 git 标记一个 blob 或一棵树(或一个标签)?