为啥 git 标签没有出现在任何分支上?

Posted

技术标签:

【中文标题】为啥 git 标签没有出现在任何分支上?【英文标题】:Why doesn’t a git tag show up on any branch?为什么 git 标签没有出现在任何分支上? 【发布时间】:2016-10-06 13:57:42 【问题描述】:

我克隆了带有标签v1.4.9 的mosquitto repo。但是,标记的提交似乎不在分支上。

怎么会这样?作者是否真的在自己的仓库中保留了一个分支,但只将标签从该分支推送到 GitHub?还是他只是对标签做出承诺?

我把标签做成了本地分支

$ git checkout -b work149 v1.4.9

并查看了分支上的最后一次提交:

$ git log -1
commit 91bfd82491f90e24b6fe9c036f0b04a1f5c14a89
Merge: bf959ef 2d0af73
Author: Roger A. Light <roger@atchoo.org>
Date:   Thu Jun 2 22:05:34 2016 +0100

    Merge branch 'fixes'

此提交比fixes 分支提前一个。

使用git log --graph,我可以在同一个分支上看到更早的提交(不是fixes 分支,而是我试图理解的一个分支):

* |   commit bf959ef9b0ae0e4d74bf80158ffb0b7c69da533d
|\ \  Merge: 646e0a0 5cca6b4
| |/  Author: Roger A. Light <roger@atchoo.org>
| |   Date:   Sun Feb 14 14:38:42 2016 +0000
| |
| |       Merge branch 'fixes'
| |

你如何找出一个标签是否在一个分支上以及在哪个分支上?最左边的垂直条是否表示分支以及遥控器上的分支在哪里?

这是一种常见的做法吗?

discussion thread “Git pull doesn’t get the tags” 提到“正在跟踪的分支头”和“未提交”。我想知道git clone 命令是否将克隆配置为不跟踪远程上的所有分支,或者repo 以某种方式使标签变为非提交?

【问题讨论】:

标签和分支只是提交的指针,with different semantics。标记根本不需要与分支重合。 具体来说,如何创建一个不在任何分支上的标签并将该标签推送到github?如何对标签进行版本控制和跟踪? 标签没有版本化。正如 Jubobs 所说,它们只是分支名称的变体。更具体地说,Git 使用一种称为“引用”的通用形式:引用只是解析为哈希 ID(通常是提交 ID)的名称。分支是以特定方式移动的引用,而标记是永远不会移动的引用(并且可以使用辅助的“带注释的标记”对象来指向提交)。按照他评论中提供的链接 Jubobs。 【参考方案1】:

我错误地做了类似的事情:我正要推送一个新版本,我在我的 PC 上提交了所有内容并添加了一个标签。

然后我做了git push --tags,错误地认为它会推送主分支标签。然后我在 github 上创建了一个版本。发布指向最后的更改,但主分支落后了。我不得不再次推动,一切都对齐了。

值得注意的是所有文件实际上都是使用第一个命令推送的(我从输出中看到它,你知道:创建增量等)。在第二次推送中,传输的字节数报告为 0,所以我猜只推送了分支元数据。

【讨论】:

【参考方案2】:

我的猜测是作者可能有一个包含91bfd82491f 的分支,标记了该提交,推送了标记,然后随后删除了该分支。您也是正确的,作者可能有一个指向同一提交但仅推送标签而不是分支的本地分支。

使用检查哪个或哪些分支包含v1.4.9

git branch -a --contains v1.4.9

运行该命令没有输出,这确认它不在自己的分支上。相比之下,寻找v1.4.8

$ git branch -a --contains v1.4.8
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/debian
  remotes/origin/master

在任何分支之外直接创建标记提交的一种方法是使用detached HEAD 操作,这就是HEAD 不引用命名分支的地方。在 mosquitto 克隆中,您可以通过运行到达那里

git checkout v1.4.9

这会给你一个喋喋不休的警告。

注意:查看“v1.4.9”。

您处于“分离 HEAD”状态。你可以环顾四周,做实验
更改并提交它们,您可以丢弃您在此所做的任何提交
在不影响任何分支的情况下执行另一次结帐。

如果你想创建一个新分支来保留你创建的提交,你可以
再次使用 -b 和 checkout 命令来执行此操作(现在或以后)。例子:

  git checkout -b 

HEAD 现在位于 91bfd82... 合并分支“修复”

此时,git 会创建更多的提交。例如:

$ touch look-ma-no-branch ; git add look-ma-no-branch

$ git commit -m 'Look, Ma! No branch!'
[detached HEAD 51a0ac2] Look, Ma! No branch!
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 look-ma-no-branch

这个新的提交51a0ac2在任何分支上都不存在,我们可以确认。

$ git branch -a --contains 51a0ac2
* (HEAD detached from v1.4.9)

为了好玩,我们也给它加个标签吧。

git tag -a -m 'Tag branchless commit' v1.4.9.1

使用git checkout master 切换回master 分支,我们可以使用git lolagit log --graph --decorate --pretty=oneline --abbrev-commit --all 的别名)来查看新标签看起来与其祖先相似。

$ git lola
* 51a0ac2(标签:v1.4.9.1)看,妈!没有分店!
* 91bfd82(标签:v1.4.9)合并分支“修复”
|\
| | * 1cd4092 (origin/fixes) [184] 当 WITH_DOCS=no 时不要尝试安装文档。
| | * 63416e6 ;
| | * 5d96c3d [186] 使用 websockets 侦听器和 libwebsockts 2.x 修复 TLS 操作。
| |/
| * 2d0af73 凹凸版本号。
| | * 8ee1ad8 (origin/coverity-fixes) 合并分支'fixes'到coverity-fixes
[...]

使用确认它不存在于任何分支上

git branch -a --contains v1.4.9.1

因为你问,不,这根本不是一个常见的 git 工作流程。

【讨论】:

啊,太棒了!我也猜到作者标记了一个分支,然后删除了这个分支,然后只推送了这个标签。但它看起来太多额外的步骤只会让其他人感到困惑。很高兴知道这不是一种常见的做法。

以上是关于为啥 git 标签没有出现在任何分支上?的主要内容,如果未能解决你的问题,请参考以下文章

Git:如何找出标签在哪个分支上?

git pull后为啥分支没有更新

为啥 git 不定期运行 git fetch?

用git创建一个中间分支

git上master的更新分支,但缺少新版本

Git:当我还没有提取更新时,为啥 git 会说“您的分支与 origin/main 是最新的”?