【问题标题】:How to use Git to tag a commit rather than a hash如何使用 Git 标记提交而不是哈希
【发布时间】:2014-04-13 09:30:08
【问题描述】:

我有大量的提交,带有各种版本标签,即:

root->x->x->1->x->x->x->2->x->x->3->x->4->x->x->x->5->master

我想在此开头附近插入一个新提交。问题是,我需要检查并重新标记所有内容,因为我的树最终看起来像这样:

root->x->x->y->x->x->x->x->x->x->x->x->x->x->x->x->x->x->master
         \->1->x->x->x->2->x->x->3->x->4->x->x->x->5

有没有一种方法可以标记特定的提交,而不是特定的哈希?这样当我进行变基时,标签会应用于新树中的相同特定提交,而不是原始提交?

注意:我对说教不感兴趣 - 请不要发布任何回答,例如“你做错了”或“版本控制不应该这样工作”,除非你也可以提供建设性的替代方案。我需要一种方法来标记在 rebase 后将持续存在的提交,即使唯一可能的解决方案是“Git 不这样做,而是使用 X”。

【问题讨论】:

  • 我将其作为评论发布只是因为您不想要这样的答案。 Git 不是那样工作的。 Git 中的提交具有加密完整性。您不能在不影响哈希的情况下更改它们的父级、作者、消息或补丁。根据补丁识别一个提交与另一个提交相同将是外部工具/命令的工作。
  • 你的问题标题本身揭示了对 git 工作原理的深刻误解。出于所有意图和目的,哈希 is 提交。最终,您无法以任何其他方式明确识别提交。所有其他指定提交的方法都在后台解析为哈希。
  • @HaralanDobrev 但是当我做一个变基时,git 会重新计算所有的哈希值。那么它不能检测到哈希已经改变,并移动相关的标签指向新的提交吗?
  • @Benubird,插入一个提交只是你可以用 rebase 做的许多事情中的 一个。您可以改写提交消息,直接编辑提交的更改,将多个提交压缩为一个(如果您愿意,还可以改写消息),重新排序提交,完全省略某些提交,添加全新的提交......在大多数情况下没有任何自动方式来判断哪些“新”提交对应于“旧”提交。
  • 重点是,哈希不只是“重新计算”——相反,对于您正在创建的 new 提交,哈希是计算的,这(内部)与您基于它们的旧提交没有任何关系。我确实得到了您的问题,但是标签的全部目的是成为指向特定修订版的可靠 static 指针。但是,请参阅我的回答,了解一种“伪标记”提交的方式,该方式将继续通过变基。

标签: git version-control versioning rebase git-tag


【解决方案1】:

这是我见过许多存储库使用的替代解决方案。

  • 为您要维护的每个主要版本创建一个分支。
  • 将修复/更新推送到每个分支。尽可能在它们之间使用合并/rebase/cherry-picking,以避免重复工作。
  • 用次要/补丁版本标记那些分支中的提交。

例子:

  • 你有一个master 分支。
  • 你发布版本1.0.0指向当前的master
  • 您继续推送到master 并发布1.1.0 版本。
  • 然后您进行重大重构/向后不兼容的更改并发布2.0.0 版本。
  • 可以(并且应该)创建一个 1.x 分支,指向之前的 1.1.0 版本。
  • 然后您推送一个错误修复(在master 中),它会影响2.x1.x 版本。
  • 将提交标记为2.0.1。在1.x 分支中挑选它并将其标记为1.1.1

此工作流程有多种变化。您始终可以为您的主要版本创建一个分支,master 分支可能是您下一个主要版本的活动开发分支。

我认为这是通过更深入地解决您的工作流程的根本原因来解决您的问题 - 将更改推送到多个版本。


我还应该提到,在推送标签之后更改标签指向的内容总是不好的。非常糟糕。

【讨论】:

  • 这是我们从 clearcase 迁移到 git 时采取的解决方案。在 clearcase 中,移动标签(实际上是标签)是标准做法。分支是 Git 提供的足够接近的功能。
  • 我刚刚写了一个替代答案;您的答案更适合生产使用,但 LESS='+/:/<text>' man gitrevisions 会受到冷遇。 :)
【解决方案2】:

...请不要发布任何回答,例如“您做错了”或“版本控制不应该这样工作”,除非您还可以提供建设性的替代方案。我需要一种方法来标记在变基后将持续存在的提交...

你做错了;这不是版本控制应该如何工作的。 ? 现在我的建设性替代方案 - 我确实有一个,它不是“Git不这样做。”

使用“标签”已经过时了。如果您确实使用了 git 标签,即使您将一些脚本组合在一起,这些脚本会在每次 rebase 时删除旧标签并创建新标签,您的新标签也不会被与您合作的任何其他用户拉取,从而使标签比没用,因为它们会积极误导。 (有关此的更多信息,请参阅LESS=+/DISCUSSION man git-tag。)

但是,有一种简洁优雅的方式可以完成您的目标,而无需使用标签。请注意,它不允许您在事后“伪标记”提交而不通过变基来修改该提交,但由于您已经经常变基,我相信它会非常适合您的工作流程。

我的伪标签方法的关键是了解一种很少使用的指定 git 版本的方法。请参阅LESS='+/:/<text>' man gitrevisions 阅读。

确定一个简短且不会意外出现在提交消息中的文本字符串,并将其用作伪标签的前缀。例如,my-pseudo-tag-

然后,对于您想要伪标记的任何提交,修改该提交消息(使用 rebase)以包含字符串,例如,my-pseudo-tag-v0.7.5

现在任何时候你想引用那个伪标签,例如要查看该版本,或创建指向那里的新分支,请使用 git 修订说明符,如下所示:

git checkout :/my-pseudo-tag-v0.7.5
git checkout -b new_branch :/my-pseudo-tag-v1.3.0

瞧!由于您的伪标签实际上是提交消息的一部分,而不是指向提交的单独对象,因此它们不受变基的影响,并且仍然只能在您希望找到它们的提交消息中找到!

换句话说,标记在变基后将持续存在的提交的方法是在提交消息中包含特定文本,这些文本只能在那个提交的消息中找到。

(当然,如果您正在与其他人一起工作,您将不得不想出一些方法来确保他们不会在自己的提交消息中使用“保留字”......但这超出了你的问题和我的解决方案。)


注意:请不要对他人可用的提交进行变基;这将给未来带来麻烦。(这是针对任何未来的读者,而不是这个问题的原始海报,其工作流程显然需要重新定位。)

【讨论】:

    猜你喜欢
    • 2019-06-10
    • 2018-06-21
    • 1970-01-01
    • 2023-03-16
    • 2017-09-09
    • 1970-01-01
    • 2013-12-26
    • 2023-03-26
    • 2020-02-27
    相关资源
    最近更新 更多