使用git标签保存存储库的状态

时间:2014-08-18 23:29:04

标签: git

我一直在读一些关于git标签的内容,我觉得我脑子里有点困惑。我看到标签可用于提交。所以,假设这是我的回购中发生的事情,

        提交 - C1         提交 - C2         承诺 - C3         承诺 - C4         提交 - C5

此时,据说5个提交进入了回购。如果我运行git tag -a TagV1.0 -m“first tag”,它会创建一个基本上保存当前repo状态的标签,对吗?运行此命令时的所有文件,而不仅仅是Commit C5中的文件。它是运行命令时回购的快照吗?

创建标签后。        提交 - C6进来。如果我做git tag -a -f TagV1.0 -m“更新标签”。这包括所有提交,然后是C6。是吗?

创建标签后,如果提交了6,7,8。我可以强制更新标签,只包括7而不是6和8吗?

感谢您的光临。

2 个答案:

答案 0 :(得分:3)

标记本身不会保存存储库的状态。实际上,除非你考虑“记下当前提交的SHA-1”以“保存”某些内容,否则它保存根本不会 1,3

$ git rev-parse HEAD
d1574b852963482d4b482992ad6343691082412f

上面的40个字符“数字”是当前提交。所有git tag都会将其写入某个文件中。 2

要真正理解这一点,您需要知道:

  • 每次提交都是“永远”。 3 它的“真实姓名”,大丑陋的SHA-1,唯一标识该提交,仅提交。 SHA-1实际上是提交内容的密码校验和,包括提交时间的时间戳,作者姓名和电子邮件等。
  • 每次提交都包含其父提交的原始SHA-1。这是从提交C5开始,git可以找到C4C5包含C4的真实名称,作为C5自己内容的一部分。然后C4让git找到C3,依此类推。
  • 就git而言,任何引用名称 - 主要显而易见的是分支和标记名称,但是有许多其他形式的引用 - 只是一种方法来提出一个起始SHA-1。

当你(或git)将其中一个SHA-1真实名称存储在各种项目 - 存储库对象(如提交)或根据标记或分支名称命名的文件或其他任何内容时 - 我们说这个“指向”您存储的真实姓名的对象。因此C5指向C4C4指向C3,依此类推。

因此,如果您有一个指向C5的标记,并且您在存储库中创建了新的提交,那么标记仍然只指向C5 4 如果你想让它指向其他地方 - 例如你的新提交C6 - 你必须删除旧的提交并创建一个新的(或者,实际上,只是覆盖文件的内容,只要它在它自己的私人文件,不像脚注2中的压缩参考那样共享。


1 这并非完全正确:带注释的标记将注释保存在存储库中,然后将相应的轻量级标记指向新保存的对象。存储库中带注释的标记具有自己的SHA-1,并且包含作为注释的一部分的任何标记的SHA-1。

2 该文件为.git/refs/tags/tagname,但最终可以“打包”并与其他参考文件一起移至.git/packed-refs

3 好吧,差不多了。没有传入引用的提交或任何git存储库对象都有资格进行垃圾回收。这意味着每个引用实际上做了两件事:给你一个原始SHA-1的名称,并且 - 至少可能保护这个SHA-1命名的对象,从Grim Collector中保存它。在特定意义上,标记可以说是“保存”的东西 - 但通常,标记名称只是一种方式来达到该提交。例如,在您C6之后,您可以通过从分支名称开始并移至其父级来到达C5;这足以保护C5

4 这应该会让你停下来想知道:嘿,等等,那么一旦我做了分支,我的新提交C6如何自动包含它?答案是:作为提交C6过程的一部分,git会自动删除并重新创建它。这真的是什么使得分支名称特别:你可以告诉git“get on this branch”,git通过在某处写下分支名称, 5 然后当你进行新的提交时,git会看到你在那个分支上并自动更新参考文件。

5 具体来说,它将当前分支名称写入文件.git/HEAD。所以git rev-parse HEAD,如上所示,读取HEAD文件,发现它命名一个分支,然后读取分支文件,现在git具有当前的原始SHA-1“真实名称”承诺。或者,如果你问git你在哪个分支,它会读取HEAD文件,发现它命名了一个分支,然后停在那里并打印出分支名称。

答案 1 :(得分:1)

在git中,每次提交都是存储库的完整快照。标签只是一个标记,允许识别一些提交。

正如您所说,如果您想要包含其他提交,则只需删除标记并在所需的提交中创建新标记。