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

发布于 2025-01-21 10:34:41 字数 1584 浏览 6 评论 0 原文

快速介绍:在Mercurial中,有两种不同的方式来指代更改。

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

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

可以将修订数字指定为Mercurial作为本地修订号,完整的40位哈希或“短形式标识符”。后者给出了哈希的独特前缀;也就是说,如果只有一个完整的哈希从给定的字符串开始,则匹配更改的字符串。

我发现在某些情况下,给定的十进制数字,在某些情况下,即使没有任何修订,例如 hg log 带有 -r switch)也将匹配一些修订版给定号码的本地修订足够多,可以匹配本地修订号。

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

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 < /代码>作为本地修订号。

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

Quick intro: In Mercurial there are two different ways to numerically refer to a changeset.

First, there's the node ID hash. It is global and functions like a git commit hash. It consists of 40 hexadecimal digits.

Second, there's the local revision number. It is a decimal number that starts at 0 and counts up. Unlike the node hash, this is local, meaning the same changeset can have different local revision numbers in two different repos. This depends on what other changesets are present in each repo and depends even on the order each repo received their changesets.

A revision can be specified numerically to Mercurial as a local revision number, a full 40-digit hash, or "a short-form identifier". The latter gives a unique prefix of a hash; that is, if only one full hash starts with the given string then the string matches that changeset.

I found that in certain cases, Mercurial commands (such as hg log with an -r switch), given plain decimal numbers, will match some revision even though there aren't enough local revisions for the given number to match as a local revision number.

Here's an example I constructed after coming across such a case by chance:

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$

As is evident, hg log -r 9 matches a changeset even though there aren't that many changesets to match the 9 as a local revision number.

The question: Why is this? Additionally, how can we avoid matching a nonexistent local revision number?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

丘比特射中我 2025-01-28 10:34:41

这是由于Mercurial解析了修订指定符。这是 Olivia Mackall如何解释它 2014:

这是十六进制标识符:

60912EB2667DE45415EFF601BFC045AE0FE8DB42

看看它是如何从6开始的?如果您要求修订6,Mercurial将:

a)寻找修订6

b)如果失败,请寻找以“ 6”

开始的十六进制标识符

c)如果我们发现多个匹配项,请抱怨

d)如果我们找不到匹配项,请抱怨

e)我们找到了一场比赛:成功!

也就是说,如果 Hg log -r 9 与任何本地修订号不匹配(因为存储库中的10个更改少于十个更改),则Mercurial Next将与一个恰好以一个节点匹配 9

为了避免这种歧义, Hg log -r'Rev(9)'仅匹配本地修订号, hg log -r'ID(9)'仅匹配前缀或完整的哈希。

在RevSets的文档中

“ id(string)”
给定的十六进制字符串前缀指定的不明式修订。

和:

“ rev(number)”
使用给定的数字标识符进行修订。

不幸的是,此页面和修订版的帮助页面从6.1版开始,明确指出可以匹配的数字之间的模棱两可,即本地修订号或节点哈希前缀。我引用的2014年邮件列表线程确实包含建议以澄清这一点,但似乎没有任何内容。


此外,这是 a changeet消息以及如何影响我的脚本的操作:

修复使用“ Rev(X)”而不是仅仅X来引用本地Rev Number

RevSets语法明确指的是本地修订版
数字是将数字包装在 rev()中。没有这个,一个数字
这不存在(例如 -r 2 )可能会被误解以参考
一个具有节点哈希的更改,从请求开始
编号。

在我们的情况下,此错误在修订后碰巧采取了行动
2022-04-02 16:10:42 2022 z“从CP850更改为UTF8”
添加后的第二天被转换为第二个
(本地修订号1)从SVN存储库进行更改。这
特定 hg convert 命令是:

hg转换svn-mirror dest \
-config hooks.pretxncommit.checkcommitmesgage = true \
-config convert.svn.startrev = 1152

这创建了一个称为 1:2ec9f101bc31 的更改集
修订。缺少本地修订编号2, -r 2 拾取了
这种变化是因为它的哈希始于数字“ 2”。
tnus newnode变量收到了更改集哈希
更改集。因为我们的 hg rebase 命令已配置为保留
空更改集,更改集已在其上方添加
目的地存储库中的现有副本。

自akt.sh脚本以来会选择错误的修订
目的地存储库中的数字,并以
表示“修订不同!”的消息。

This is due to how Mercurial parses revision specifiers. Here's how Olivia Mackall explains it in a mail from 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!

That is, if hg log -r 9 doesn't match any local revision number (because there are less than ten changesets in the repo), Mercurial next will match a node hash that happens to start with a 9.

To avoid this ambiguity, she responded that one should use hg log -r 'rev(9)' to match only local revision numbers, and hg log -r 'id(9)' to match only prefixes or full hashes.

In the documentation on revsets, these predicates are listed as:

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

And:

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

Unfortunately, both this page and the help page on revisions do not (as of version 6.1) explicitly point out the ambiguity between numbers that can match either as local revision numbers or node hash prefixes. The 2014 mailing list thread I quoted does contain suggestions to clarify this but it appears nothing came off it.


Additionally, here is a changeset message in which I explained the entire affair and how it came to affect the operation of a script of mine:

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!".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文