我一直在读一些关于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吗?
感谢您的光临。
答案 0 :(得分:3)
标记本身不会保存存储库的状态。实际上,除非你考虑“记下当前提交的SHA-1”以“保存”某些内容,否则它保存根本不会 1,3 :
$ git rev-parse HEAD
d1574b852963482d4b482992ad6343691082412f
上面的40个字符“数字”是当前提交。所有git tag
都会将其写入某个文件中。 2
要真正理解这一点,您需要知道:
C5
开始,git可以找到C4
:C5
包含C4
的真实名称,作为C5
自己内容的一部分。然后C4
让git找到C3
,依此类推。当你(或git)将其中一个SHA-1真实名称存储在各种项目 - 存储库对象(如提交)或根据标记或分支名称命名的文件或其他任何内容时 - 我们说这个“指向”您存储的真实姓名的对象。因此C5
指向C4
,C4
指向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中,每次提交都是存储库的完整快照。标签只是一个标记,允许识别一些提交。
正如您所说,如果您想要包含其他提交,则只需删除标记并在所需的提交中创建新标记。