git describe 何时以及为什么不显示最新标签?

问题描述

我有三个分支:devstagingmaster。当我执行 git describe 时,无论检出哪个分支,结果都是 v0.1

接下来,我将描述更改 dev 添加版本标签并合并到 stagingmaster 这个新版本的工作流程。

  1. git checkout dev
  2. 做一些改变
  3. git add --all && git commit -m 'just some testing'
  4. git tag -a v0.19.0
  5. git push && git push --tags
  6. git checkout staging
  7. git merge dev
  8. git push
  9. git checkout master
  10. git merge staging
  11. git push

现在我在每个分支上运行 describe

- git checkout dev && git describe && git describe --abbrev=0

结果:

v0.19.0-1-ge147b2d
v0.19.0

我的预期:

v0.19.0-1-ge147b2d
v0.19.0
  • git checkout staging && git describe && git describe --abbrev=0

结果:

v0.17.0-3-g684216f
v0.17.0

我的预期:

v0.19.0-xxxxx
v0.19.0
  • git checkout master && git describe && git describe --abbrev=0

结果:

v0.17.0-16-g99c19c9
v0.17.0

我的预期:

v0.19.0-xxxxx
v0.19.0

enter image description here

这是为什么?我怎么能有这样一个过程,我在 dev 中进行一些更改,然后添加一个标签,然后将这些更改与标签一起传播到所有其他分支?

解决方法

您应该编写您实际运行的所有命令,而不是尝试使用英语,因为它似乎不能足够准确地解释情况。例如,您的措辞使用了“合并到”和“合并到”,它们可能会也可能不会为您描述同一件事。对于合并,您通常会执行类似 git checkout some-local-branch && git fetch && git merge origin/some-other-branch 的操作。如果您不能确定自己了解整个情况,那么所有细节都可能很重要。如果你运行一些命令,例如通过 ssh 连接的远程机器,请务必指出这一点。

从问题(措辞 2021-04-27T14:24:13+00:00)看来,您的流程 2 缺少 git push --tags(或者可能是 git fetch),如果您尝试运行 git describe somewhere else 但原始存储库(即您的实际工作目录)您根本看不到新标签。

我建议在您尝试使用的所有工作区(或“分支”)中以 git show NEWTAG 开头。您应该在每个工作区上获得相同的 SHA-1。您还可以运行 git show HEAD 来验证当前 HEAD 是否真正匹配您认为应该匹配的内容。此外,如果您可以运行 gitk,您可以尝试运行 gitk NEWTAG HEAD 来获得问题的视觉表示,甚至 gitk --all -n 10000 以显示最多 10000 次最新提交的所有分支。

如果您不能使用gitk,您也可以尝试运行例如git log --oneline --graph --decorate -n 50。作为替代方案,您还可以运行 git log --oneline --graph --decorate -n 50 --format=%h%d 以列出来自 DAG 的最新 50 次没有标题的提交,以便您在需要更多帮助时可以在 SO 中共享结果。

看到截图后更新

您的分支 master 与您的任何标签不在同一位置,因此 git describe 不应发出任何给定的标签名称作为唯一输出。相反,它应该说类似 v0.2-4-gf5d6ced 的内容,这基本上意味着“v0.2 加上 4 个补丁,其中 HEAD 指向以 f5d6ced 开头的 SHA-1”。此示例的四个补丁是 a5312dc、7dceb15、b4cd4f6 和 f5d6ced,它们未包含在下面的 v0.2 中。

这是我创建的示例:

*   f5d6ced (HEAD -> master) Merge branch 'staging'
|\  
| *   b4cd4f6 (staging) Merge branch 'dev' into staging
| |\  
| | * 1fa7a37 (tag: v0.2,dev) Updated testfile yet again in branch dev
* | |   7dceb15 (tag: test) Merge branch 'staging'
|\ \ \  
| |/ /  
| * |   a5312dc Merge branch 'dev' into staging
| |\ \  
|/ / /  
| | _   
| * 96cd0ac (tag: v0.1) Updated testfile in branch dev
|/  
* d626941 Added testfile in branch dev

Screenshot of the above textual repsentation

v0.1v0.2 是带注释的标签,而 test 是非带注释的标签。

$ git checkout dev && git describe
Switched to branch 'dev'
v0.2

$ git checkout staging && git describe
Switched to branch 'staging'
v0.2-2-gb4cd4f6

$ git checkout master && git describe
Switched to branch 'master'
v0.2-4-gf5d6ced

$ git checkout master && git describe --tags
Already on 'master'
test-3-gf5d6ced

这是因为当您创建合并时,您创建了一个新提交,该提交显然将具有自己的 SHA-1 标识符,并且现有标签不指向合并,因为标签始终引用特定版本。

你确定你实际上没有在跑步吗? git describe --abbrev=0 只从最近的标签中选择一个标签,并且可能更喜欢任何给定合并的第一个父标签?

如果你真的想弄清楚你的给定分支已经包含哪些标签,你可以运行如下:

$ git checkout master && git tag --merged
Switched to branch 'master'
test
v0.1
v0.2

按标签创建时间排序,最新在前

$ git checkout master && git tag --sort=-authordate --merged
Already on 'master'
test
v0.2
v0.1

如果你想要只是最新的标签,你可以运行

git tag --list --sort=-authordate --merged | head -n1

有关详细信息,请参阅 git help tag。对于这种情况,latest 表示给定标签的创作时间戳。对于标签,作者时间戳和提交时间戳是相等的,但据我所知,这不是强制的。如果差异对您很重要,则只有您自己决定需要哪个时间戳。

对您的特定“错误”情况的进一步解释:您实际上并没有像您声称的那样运行 git describe,而是 git describe --abbrev=0 列出了最接近的 标签。请注意,这是在 DAG 拓扑中,它可能与 latestnewest 标签完全不同。对于您的示例,v0.17v0.19 与分支 HEADstaging 的距离为 1,与 HEADmaster 的距离为 2。此外,较旧的标签来自第一个父标签,这就是您得到 v0.17 作为响应的原因。如果您想要包含在给定分支中的最新标记,我建议改用 git tag --list --sort=-authordate --merged | head -n1。但是,我强烈建议在开发或暂存分支中标记主分支版本而不是随机补丁。然后你可以只使用 git describe 而没有任何标志