结帐 git 标签存在于多个分支上



我读了很多SO帖子,但没有一个让我理解git标签的真正工作原理,尤其是关于它们与分支的链接。我认为这是由于对 git 原则的误解。也许有人可以帮助我。

假设我有以下两个分支masterdevelopK合并提交:

-A-B-C-D-E-F-G-K-L-M (master)
-H-I-J-/     (develop)

如果我标记J提交,则此标记将位于两个分支上(因为合并(。 那么当我checkout这个标签时,我会有什么版本?包含master分支的EFG提交或来自develop分支的提交。不确定我是否清楚我想了解的内容。我知道标签不引用分支,而只引用提交。但是签出标签也会恢复提交历史,不是吗?

我假设分支的位置是这样的(反正这并不重要(:

v------- master
-A-B-C--D-E-F--G-K-L-M
-H-I-J-/
^------ develop

如果我标记J提交,则此标记将在两个分支上(因为合并(。

标记是指向提交的只读指针。一个分支也指向一个提交,但它被许多Git命令移动到另一个提交(git commitgit mergegit rebasegit pullgit reset最常见的(。

鉴于两个分支的当前位置,实际上可以从两个分支访问J提交。git commitgit mergegit pull不会改变这种现状。但是git resetgit rebase可以在不是J后代的提交上移动分支,在这种情况下,J无法从移动的分支访问。

因此,当我签出此标签时,我会使用什么版本?包含master分支的 E,F,G 提交或来自develop分支的提交。

git checkout更改您的工作副本,使其与签出的提交相同。

如果将分支传递给git checkout则也会使该分支成为当前分支(也称为HEAD(。如果您传递给git checkout不是分支的引用(它可以是标签、提交哈希或其他解析为单个提交的修订规范(,则将存储库置于名为"分离HEAD">的状态。这意味着没有当前分支。
不建议在分离的HEAD状态下工作(除非您知道自己在做什么(,因为以这种方式创建的提交不会由任何分支指向,并且一旦您签出另一个分支(或标记或提交(就会丢失。

假设您运行:

git tag tagJ J

要在提交J上创建名为tagJ的标记,以下两个命令执行相同的操作:

git checkout J
git checkout tagJ

它们更改工作树和索引以匹配提交J中记录的项目状态。他们将存储库设置为分离的HEAD状态。

命令:

git checkout develop

更改工作树和索引的方式与上述两个命令相同。但是,它不会将存储库设置为分离的HEAD状态,而是develop设置为HEAD(当前分支(。

但是签出标签也会恢复提交历史,不是吗?

历史记录由分支和标记确定。可从任何分支或标记访问的任何提交都是历史记录的一部分。如果删除master分支,则存储库的历史记录将仅包含可从develop分支访问的提交(即ABCHIJ(。如果删除develop分支(并保留master分支(,则不会丢失任何内容,因为图形中可见的所有提交都可以从提交M(由master分支指向(访问。

您可以签出标签,但这会使您的存储库处于分离的 HEAD 状态。本质上不在任何分支上。

请参阅 Git 标记。

最新更新