6

在 git 中,假设我有一个分支 master 和一个标签 0.0.1,如果我执行以下操作:

git checkout 0.0.1
git branch -b random-fix
# some changes...
git checkout master
git merge random-fix

来自标记的分支在内部创建对由分支主控中的标记标记的提交的引用,或者分支来自“标记本身”,就好像标记是某种分支一样?

我问这个是因为当我结帐到一个标签时,我会处于“分离的头脑”或类似的状态,对吧?知道这一点让我想到了标签分支。

4

2 回答 2

7

标签 参考 提交

标签是对提交的引用。具体来说,轻量级标签只是使用用户定义名称指向给定提交的引用。例如:

$ git log
commit e0e92bc337b246696aec5c214507321c7526c1e9
Author: John Doe <john.doe@example.com>
Date:   Thu Sep 26 14:38:36 2013 -0400

    Empty initial commit.

$ git tag v0.0.1

$ cat .git/refs/tags/v0.0.1 
e0e92bc337b246696aec5c214507321c7526c1e9

在这两种情况下,实际的 SHA-1 是相同的。换句话说,标签只是指向提交的指针。

使用标签作为提交标识符

您可以像从提交标识符一样从标签分支。例如,以下两个命令实际上是同一件事:

  • git checkout -b new_branch v0.0.1
  • git checkout -b new_branch e0e92bc337b246696aec5c214507321c7526c1e9

新分支的起点是否列为标记、SHA-1 或其他某种形式的修订选择对 Git 没有影响。

于 2013-09-26T18:49:34.500 回答
5

(这也许应该是一个评论,但它太大了,需要很好的格式:-) ...另外,如果你点击一些链接,我似乎心情很古怪......)

理解这一点的关键——我想你已经在那里了,但是让我们把它放在 SO 文章中以便让下一位读者清楚——是这样的:

所有 git refs 最终命名(指向)单个提交。

对于标签(无论是轻量级的还是带注释的)、分支、“远程分支”、git “notes”引用、“stash”等都是如此。他们都命名了一次提交,仅此而已。(好吧,好吧,不完全是:从技术上讲,标签可以命名存储库中的任何对象。事实上,这就是带注释的标签的工作方式:有一个轻量级标签,它命名一个存储库对象,它带注释的标签,然后带注释的标签命名为提交对象。这也是HEAD工作原理:它通常命名另一个 ref,然后命名提交。因此,有时您必须从洋葱上剥几层才能命中提交。命名 blob 或树对象是可能的,但通常,实际上什么都没有这样做。)

(提交的“真实名称”当然是 SHA-1 值。)

使分支引用名称“特殊”的原因同样简单:

分支引用是在添加新提交时自动移动到新分支提示的名称。

具体来说,表单的 ref指向某个提交(根据定义,因为名称指向提交)。当您“打开”该分支1并执行一些 git 操作以添加提交时,例如or or ,git 会将新提交粘贴到存储库中,然后将名称重新指向新提交。这就是它所要做的!refs/heads/branchnamegit commitgit mergegit cherry-pick

我们认为的“分支”是通过从尖端开始——名称指向的提交——并使用每个提交的父级或父级向后工作而形成的。如果提交有一个父级,则它是“在分支上”的普通提交。如果它有两个或更多,那就是“合并”,您可以跟随它的所有父项查找合并的内容。如果它根本没有父母,它就是一个根提交(就像一个新仓库中的初始提交——你实际上可以有多个根;例如,git "notes" 就是这样做的)。

如果您将七个分支标签放在一个提交上,那么您现在有七个2名称用于“分支”。如果您将其清除为一个,那么它当然不会那么混乱,但是 git 不会在意任何一种方式。(Git 只关心你是否将其归为零。现在分支仍然存在,但它真的很难找到,它有资格进行垃圾 回收。)

既然我们在这个话题上,让我们也记下“远程分支”。(我从来没有对“远程分支”这个名字很满意,但我没有更好的,所以让我们定义它。)“远程分支”是表单的本地引用,其中rname是远程(例如)和bname是远程上的分支名称,即,如果您登录该远程并查看那里的分支,则后面的部分。你不能“打开”远程分支——如果你git 给你一个“分离的 HEAD” ——但是这些分支名称自动更新:当你使用refs/remotes/rname/bnameoriginrefs/heads/git checkout origin/mastergit fetch要从远程获取新的提交,您还需要获取新的分支提示。换句话说,不是将名称移动到新的分支提示中,而是让其他人(在遥控器上)这样做,然后当您从他们那里获取时,您会立即获取他们的最新版本。


1要“在分支上”,HEAD引用必须是“间接”引用,例如ref: refs/heads/master. HEAD相反,当它被“分离”时,它包含一个原始的 SHA-1 值。你仍然可以添加提交;它们被添加到未标记的分支中。中的引用HEAD使它们不会被垃圾收集。

2或更多,如果有标签。假设没有标签

3没有脚注三。

于 2013-09-27T02:03:16.760 回答