是否允许在Mercurial中修改标签?

时间:2015-11-11 22:25:47

标签: mercurial rebase

要更新我们软件中的版本号,脚本会执行以下操作:

$ hg update v3.3
(sed+awk magic to edit version numbers in code base)
$ hg commit -m"Create v3.3.50"
$ hg tag v3.3.50
$ hg push    
abort: push creates new remote head 101b0ff402c6 on branch 'v3.3'!
(pull and merge or see "hg help push" for details about pushing new heads)
$ hg pull --branch v3.3 --rebase
...
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
$ hg push
...
added 2 changesets with 4 changes to 4 files

但是在提交之后,标记似乎不存在于目标存储库中:

$ hg tags | grep v3.3.50
$

令人困惑的是,标签位于.hgtags文件中:

$ grep v3.3.50 .hgtags 
e7d6c19f8dd86cdad4cb41f543d09dbe5d30405e v3.3.50

并且在修订历史中:

$ hg log -b v3.3
changeset:   7067:701358ca0f4b
branch:      v3.3
user:        Joe User <juser@example.com>
date:        Wed Nov 11 12:41:15 2015 -0800
summary:     Added tag v3.3.50 for changeset e7d6c19f8dd8

changeset:   7066:19aafdd33263
branch:      v3.3
user:        Joe User <juser@example.com>
date:        Wed Nov 11 12:41:15 2015 -0800
summary:     Create v3.3.50

hg commit / tag / push序列按预期工作,但添加rebase似乎至少部分删除了标记。标签是否需要对rebase命令进行一些特殊处理?

Mercurial版本是2.9.2,有问题的系统正在运行最新版本的Ubuntu。

3 个答案:

答案 0 :(得分:4)

这可能是一种疏忽或有意的设计,而且很难分辨出它是什么(更多内容如下)。

你可以通过更新到分支的头部并通过以下方式重新修复它来修复它:

hg tag -f -r REVID TAGNAME

能够更改或删除标签是intended design,所以这不是什么古怪的。但是,原始标记提交将保持不变。

如果您想明确指出这是标签更新,请使用

hg tag -f -e -r REVID TAGNAME

允许您编辑标记提交消息,表明它是原始标记的更新。

如果您已安装了evolve,则可以避免查找原始版本并使用:

hg tag --hidden -f -r 'successors(TAGNAME)' TAGNAME

此处,successors(...) revset函数描述了标记为TAGNAME的原始修订版所针对的修订版。

如果您已经进化或使用hg histedit(并且您的重定历史记录不包含自标记以来的合并),您也可以(原则上)更改原始标记提交,但我建议不要这样做,因为它可能有点挑剔(你基本上必须手动编辑.hgtags并更新提交消息)。

如果您希望这样做,最简单的方法就是:

hg update --hidden -r 'successors(TAGNAME)'
edit .hgtags                                 # update tag information
hg commit --amend                            # update commit message
hg evolve -a                                 # propagate changes

这与histedit有点复杂:

hg histedit -r REVID                         # REVID = tag commit
# In the histedit editor, change "pick" to "edit" for the tag commit,
# then write the file and leave the editor.
edit .hgtags                                 # update tag information
hg commit                                    # provide new commit message
hg histedit --continue                       # rebuild rest of history 

这两种方法都依赖于hg tag只进行改变.hgtags的正常提交并自动生成提交消息的事实。 Mercurial只依赖.hgtags中的信息而不检查任何元数据。我还建议事先制作一个本地克隆的存储库,以防万一你弄错了,不知道如何从中恢复。

同样,我认为这不是必要的(甚至不是一个好主意),但最终决定权归你所有。

那么,这是一个bug还是设计?在rebase期间自动移动标签的一个问题是原始版本通常会保留(hg rebase --keep或只是简单的rebase with evolve),在这种情况下,不清楚是否要移动标记或不。它也没有解决hg graft的类似问题。所以,它可能是。

答案 1 :(得分:2)

'\s*\r?\n'文件中的标记由变更集哈希标识标识。重新设置变更集会更改散列,因为在计算散列时会包含有关其父级的数据。

在您的示例输出中,“创建v3.3.50”变更集的散列值为“19aafdd33263” - 这与标记文件和标记变更集中引用的.hgtags不同。

请注意,您可以重新添加添加标记的变更集,因为标记的变更集哈希不会更改。

答案 2 :(得分:0)

我们最近也遇到了这个问题,并试图为它提供复杂的解决方案,包括历史操作和更新提交消息等。最后我们意识到,重新定义一个未刷新的变更集是错误的,因为我们正在将指向出库的唯一快照的东西移动到一个新的快照,这是不一样的,因为rebase做了什么,所以我们最终得到了以下规则并相应地更改了我们的脚本:

  

永远不要标记未按下的变更集

即。在我们的构建脚本中,我们现在pull,测试,增加版本,commitpull --rebase,如果需要, push 并记住哈希,然后{{如果需要,再次那个哈希,tagcommit(现在没有任何东西可以再被破坏),最后pull --rebase对&进行了更改#34; .hgtags&#34;

我为Mercurial打开了一个功能请求,以更好的方式解决这个问题: https://bz.mercurial-scm.org/show_bug.cgi?id=5352