version-control - 为什么 Mercurial 匹配不存在的本地修订号?

标签 version-control mercurial changeset

快速介绍:在 Mercurial 中,有两种不同的方式以数字方式引用变更集。

首先是节点 ID 哈希。它是全局的,功能类似于 git提交哈希。它由 40 个十六进制数字组成。

其次是本地修订号。它是一个从 0 开始向上计数的十进制数。与节点哈希不同,这是本地的,这意味着相同的变更集可以在两个不同的存储库中具有不同的本地修订号。这取决于每个存储库中存在哪些其他变更集,甚至取决于每个存储库收到其变更集的顺序。

可以将修订版以数字形式指定给 Mercurial,作为本地修订版号、完整的 40 位哈希值或“短格式标识符”。后者给出了哈希的唯一前缀;也就是说,如果只有一个完整哈希以给定字符串开头,则该字符串与该变更集匹配。

我发现在某些情况下,Mercurial 命令(例如带有 hg log 开关的 -r),给定纯十进制数字,将匹配某些修订版本,即使没有足够的本地修订版本来匹配给定的数字作为本地修订号。

这是我偶然遇到这种情况后构建的一个示例:

test$ hg --version
Mercurial Distributed SCM (version 6.1)
(see https://mercurial-scm.org for more information)

Copyright (C) 2005-2022 Olivia Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
test$ hg init
test$ touch a
test$ hg add a
test$ hg ci -d "1970-01-01 00:00:00 +0000" -u testuser -m a
test$ touch b
test$ hg add b
test$ hg ci -d "1970-01-01 00:00:00 +0000" -u testuser -m b
test$ hg log
changeset:   1:952880b76ae5
tag:         tip
user:        testuser
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     b

changeset:   0:d61f66df66f9
user:        testuser
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     a

test$ hg log -r 2
abort: unknown revision '2'
test$ hg log -r 9
changeset:   1:952880b76ae5
tag:         tip
user:        testuser
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     b

test$

显而易见,hg log -r 9匹配变更集,即使没有那么多变更集来匹配 9作为本地修订号。

问题:这是为什么?此外,我们如何避免匹配不存在的本地修订号?

最佳答案

这是由 Mercurial 解析修订说明符的方式决定的。这是how Olivia Mackall explains it在 2014 年的一封邮件中:

Here is a hexadecimal identifier:

60912eb2667de45415eff601bfc045ae0fe8db42

See how it starts with 6? If you ask for revision 6, Mercurial will:

a) look for revision 6

b) if that fails, look for a hex identifier starting with "6"

c) if we find more than one match, complain

d) if we find no matches, complain

e) we found one match: success!

也就是说,如果 hg log -r 9 不匹配任何本地修订号(因为存储库中的变更集少于 10 个),Mercurial next 将匹配恰好符合以下条件的节点哈希值:以 9 开头。

为了避免这种歧义,she responded that应使用 hg log -r 'rev(9)' 仅匹配本地修订号,并使用 hg log -r 'id(9)' 仅匹配前缀或完整的哈希值。

In the documentation on revsets ,这些谓词列出为:

"id(string)"
Revision non-ambiguously specified by the given hex string prefix.

还有:

"rev(number)"
Revision with the given numeric identifier.

不幸的是,此页面和 the help page on revisions不要(从版本 6.1 开始)明确指出可以匹配本地修订号或节点哈希前缀的数字之间的歧义。我引用的 2014 年邮件列表主题确实包含了澄清这一点的建议,但似乎没有任何结果。


此外,这里是a changeset message我在其中解释了整个事件以及它如何影响我的脚本的运行:

fix to use 'rev(x)' instead of just x to refer to local rev number

The revsets syntax to unambiguously refer to a local revision number is to wrap the number in rev(). Without this, a number that doesn't exist (eg -r 2) may be misinterpreted to refer to a changeset that has a node hash starting with the requested number.

In our case this bug happened to act up after the revision on at 2022-04-02 16:10:42 2022 Z "changed encoding from cp850 to utf8" which the day after it was added was converted as the second (local revision number 1) changeset from the svn repo. The particular hg convert command was:

hg convert svn-mirror DEST \
--config hooks.pretxncommit.checkcommitmessage=true \
--config convert.svn.startrev=1152

This created a changeset known as 1:2ec9f101bc31 from that svn revision. Lacking a local revision number 2, the -r 2 picked up this changeset because its hash started with the digit "2". Tnus the NEWNODE variable received the changeset hash for this changeset. Because our hg rebase command is configured to keep empty changesets, the changeset got added atop its already existing copy in the destination repo.

Ever since the akt.sh script would pick up the wrong revision number from the destination repo and abort its run with the message indicating "Revisions differ!".

关于version-control - 为什么 Mercurial 匹配不存在的本地修订号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71882801/

相关文章:

version-control - Mercurial——指定某些文件应该始终被拉出但从不被插入?

button - 我在哪里可以找到更改集中的按钮覆盖

changeset - TFS : List changesets that have not been merged

version-control - 如何将我的 Mercurial 存储库根目录移至一个目录?

linux - 文件所有权不会停留在 git 分支更改上

svn - 版本控制实现建议 (SVN)

mercurial - 在进行重大重组后,将有关已移动文件的信息告知Mercurial

mercurial - 如何使用 Mercurial 进行基于变更集的 merge ,而不是基于文件的 merge ?

mercurial - 使用像 Bitbucket 这样的免费 Mercurial 托管的问题

mysql - 无法从 liquibase gradle 插件中生成差异