偶尔会出现的一个问题是,确定您上次在 Perforce 中同步到的更改列表的最佳方法是什么。这通常需要通过自动构建系统将更改列表编号注入修订信息。
10 回答
对于自动构建系统,我建议相反:您应该首先使用以下命令从服务器获取最新的更改列表:
p4 changes -s submitted -m1
然后同步到该更改并将其记录在修订信息中。原因如下。尽管Perforce 建议使用以下方法来确定工作区同步到的更改列表:
p4 changes -m1 @clientname
他们注意到一些问题:
- 这仅在您没有从相关工作区提交任何内容时才有效。
- 客户端工作区也可能未同步到任何特定的更改列表。
还有一个他们没有提到的额外问题:
- 如果发生同步的最高更改列表从工作区中严格删除文件,则将报告下一个最高更改列表(除非它也严格删除文件)。
如果您必须先同步然后再录制,Perforce 建议运行以下命令来确定您是否被上述陷阱所困扰;它应该表明没有同步或删除任何内容:
p4 sync -n @changelist_number
只是为了自己回答这个问题,以符合 Jeff 的建议,即使用 Stackoverflow 作为保存技术片段的地方......
从命令行使用:
p4 changes -m1 @<clientname>
只需替换为您的客户规范的名称。这将产生以下形式的输出:
Change 12345 on 2008/08/21 by joebloggs@mainline-client '....top line of description...'
这很容易解析以提取更改列表编号。
您可以尝试在“p4 files”命令的输出中找到最大更改数。但是,工作目录不应包含同步后提交。这只是比
p4 changes -m1 "./...#have"
因为后者似乎在服务器上运行,并且由于“MaxResults”限制而可能在大型源树上失败。
$ p4 changes -m1 "./...#have"
Request too large (over 850000); see 'p4 help maxresults'.
$ p4 -G files "./...#have" | python c:/cygwin/usr/local/bin/p4lastchange.py
Files: 266948
2427657
其中 p4lastchange.py 基于来自JTGoldstone 的命令行演示文稿的 Using P4G.py 中的代码,Kodak Information Network/Ofoto,2005 年 4 月 15 日。
#! /usr/bin/env python
import sys, os, marshal
if os.name == "nt":
# Disable newline translation in Windows. Other operating systems do not
# translate file contents.
import msvcrt
msvcrt.setmode( sys.stdin.fileno(), os.O_BINARY )
lastcl = 0
num = 0
try:
while 1:
dict = marshal.load(sys.stdin)
num = num + 1
for key in dict.keys():
# print "%s: %s" % (key,dict[key])
if key == "change":
cl = int(dict[key])
if cl > lastcl:
lastcl = cl
except EOFError:
pass
print "Files: %s" % num
print lastcl
如果您使用的是 P4V,您可以以图形方式执行此操作:
- 在仪表板选项卡(查看->仪表板)中选择一个文件夹,您将看到该文件夹尚未更新的更改列表列表。请注意最小的数字(在最高行中)。
- 确保您在工作区树中选择了与之前在仪表板中相同的文件夹。然后转到历史选项卡(查看->历史)并向下滚动到前面提到的数字。该数字下方的数字是您当前更改列表的编号。
p4 changes -m1 @clientname
这是为我的客户做的“推荐”方式大约需要 10 分钟
这就是我使用的:
p4 cstat ...#have | grep change | awk '$3 > x { x = $3 };END { print x }'
对于同一个客户端需要 2.1 秒
您还可以使用 cstat 命令:
p4 帮助 cstat
cstat -- Dump change/sync status for current client
p4 cstat [files...]
Lists changes that are needed, had or partially synced in the current
client. The output is returned in tagged format, similar to the fstat
command.
The fields that cstat displays are:
change changelist number
status 'have', 'need' or 'partial'
对于严肃的构建(正在准备测试的构建),明确指定所需的标签或更改列表编号,同步到标签,并将其嵌入构建工件中。
如果没有给出更改列表(或标签),则使用p4 counter change
获取当前更改编号,并记录下来。但是您仍然需要使用该更改编号同步所有内容。
我认为您不能完全实现您想要的,因为一般来说,整个工作区不会同步到特定的更改列表编号。可以将某些文件显式同步到旧版本,然后单个更改列表编号是没有意义的。这就是为什么需要一个新sync
的来确保单个变更列表编号准确地代表代码版本。
关于评论:是的,我的答案是供配置经理准备构建以提供给 QA 的。我们的开发人员通常不会将同步作为构建的一部分;他们在提交之前进行构建——这样他们就可以确保他们的更改不会破坏构建或测试。在这种情况下,我们不会费心嵌入存储库标签。
使用您的方法,您假设您的整个工作区在您上次提交更改列表时已同步到 head,并且该更改列表包含您所有打开的文件。在这些假设中很容易被误解,很难发现,而且在浪费时间方面代价高昂。另一方面,解决问题很容易,没有缺点。而且由于可以明确指定更改列表编号,因此您需要什么修订版或代码库的更改速度有多快都无关紧要。
对于整个仓库(不仅仅是您的工作区/客户端)
p4 counter change
完成这项工作,只是告诉最后一个更改列表。
到目前为止,我发现的最好的方法是将同步到您想要构建的任何更改列表,然后使用 changes -m1 //...#have 来获取当前的本地更改列表(修订版)。
p4 同步 @CHANGELIST_NUM p4 更改 -m1 //...#have | awk '{打印 $2}'
为您提供可以在任何地方使用的更改列表编号。我目前正在寻找一种比 p4 changes -m1 //...#have 更简单的方法。
我不确定您是否得到了所需的答案,但我遇到了类似的问题。目标是在我们的记录器中写入项目的特定版本。问题在于,当我们制作自己的 makefile 时,整个构建系统由我们的配置管理控制。这意味着所有说“同步到某事然后做某事”的解决方案并没有真正起作用,而且我不想在我们提交时手动更改版本(错误的确定来源)。解决方案(实际上在上面的一些答案中暗示)是这样的:在我们的 makefile 中,我执行 p4 changes -m1 "./...#have" 结果是 Change change_number on date by user@client '味精' 我只是将消息创建为由记录器打印的字符串(更改编号是重要元素,但另一个也可用于快速确定某个版本是否包含您知道自己所做的更改而无需强制检查)。希望这可以帮助。