是否允许在 Mercurial 中重新定位标签?
Is rebasing a tag in Mercurial allowed?
要更新我们软件中的版本号,脚本会执行以下操作:
$ 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 的最新版本。
.hgtags
文件中的标签由变更集哈希 ID 标识。变基更改集会更改哈希,因为在计算哈希时包含有关其父项的数据。
在您的示例输出中,"Create v3.3.50" 变更集的散列值为“19aafdd33263”- 这与标签文件和标签变更集中引用的 e7d6c19f8dd8
不同。
不过请注意,您可以重新设置添加标签的变更集的基准,因为标记的变更集散列不会更改。
这要么是疏忽,要么是有意设计,很难说到底是哪一个(详情见下文)。
您可以通过更新到分支的头部并通过以下方式重新标记来修复它:
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
中的信息,不会检查任何元数据。我还建议事先在本地克隆存储库,以防万一您犯了错误并且不知道如何从中恢复。
同样,我认为这不是必需的(甚至不是一个好主意),但最终决定权在您。
那么,这是错误还是设计使然?在 rebase 期间自动移动标签的一个问题是原始修订通常会保留(hg rebase --keep
或只是简单的 rebase with evolve),在这种情况下,您不清楚是否要移动标签或不是。它也没有解决 hg graft
的类似问题。所以,它可能是。
我们最近也遇到了这个问题,并试图为其提供复杂的解决方案,包括历史操作和更新提交消息等。最后我们意识到,rebase 一个未推送的变更集是错误的,因为我们随后将指向 out 存储库的唯一快照的东西移动到一个新的快照,这是不一样的,因为 rebase 做了什么,所以我们最终采用了以下规则并相应地更改了我们的脚本:
Never tag an unpushed changeset
即在我们的构建脚本中,我们现在 pull
、测试、增量版本、commit
、pull --rebase
(如果需要)、push
并记住哈希,然后 tag
在 that 散列上,commit
,pull --rebase
如果需要再次 pull --rebase
(现在没有任何东西可以再损坏),最后 push
对“.hgtags”所做的更改。
我为 Mercurial 打开了一个功能请求以更好地解决这个问题:
https://bz.mercurial-scm.org/show_bug.cgi?id=5352
要更新我们软件中的版本号,脚本会执行以下操作:
$ 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 的最新版本。
.hgtags
文件中的标签由变更集哈希 ID 标识。变基更改集会更改哈希,因为在计算哈希时包含有关其父项的数据。
在您的示例输出中,"Create v3.3.50" 变更集的散列值为“19aafdd33263”- 这与标签文件和标签变更集中引用的 e7d6c19f8dd8
不同。
不过请注意,您可以重新设置添加标签的变更集的基准,因为标记的变更集散列不会更改。
这要么是疏忽,要么是有意设计,很难说到底是哪一个(详情见下文)。
您可以通过更新到分支的头部并通过以下方式重新标记来修复它:
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
中的信息,不会检查任何元数据。我还建议事先在本地克隆存储库,以防万一您犯了错误并且不知道如何从中恢复。
同样,我认为这不是必需的(甚至不是一个好主意),但最终决定权在您。
那么,这是错误还是设计使然?在 rebase 期间自动移动标签的一个问题是原始修订通常会保留(hg rebase --keep
或只是简单的 rebase with evolve),在这种情况下,您不清楚是否要移动标签或不是。它也没有解决 hg graft
的类似问题。所以,它可能是。
我们最近也遇到了这个问题,并试图为其提供复杂的解决方案,包括历史操作和更新提交消息等。最后我们意识到,rebase 一个未推送的变更集是错误的,因为我们随后将指向 out 存储库的唯一快照的东西移动到一个新的快照,这是不一样的,因为 rebase 做了什么,所以我们最终采用了以下规则并相应地更改了我们的脚本:
Never tag an unpushed changeset
即在我们的构建脚本中,我们现在 pull
、测试、增量版本、commit
、pull --rebase
(如果需要)、push
并记住哈希,然后 tag
在 that 散列上,commit
,pull --rebase
如果需要再次 pull --rebase
(现在没有任何东西可以再损坏),最后 push
对“.hgtags”所做的更改。
我为 Mercurial 打开了一个功能请求以更好地解决这个问题: https://bz.mercurial-scm.org/show_bug.cgi?id=5352