1

什么时候发生关键字替换?如何设置

我设置svn:keywords属性

我将这些行放在 1.txt 中并提交。

$Revision$
$Author$
4

2 回答 2

2

当且仅当svn:keywords设置了适当的值时,关键字才会在文件的 checkout/update/switch/export/cat 上展开。当提交包含关键字的文件时,客户端将关键字缩减为关键字字符串的空副本并将其发送到服务器。Subversion 不启用关键字的原因,除非svn:keywords设置了属性,否则 Subversion 永远不会更改您的文件内容,除非您告诉我们这样做,该属性会这样做。

考虑 Subversion 的 INSTALL 文档。它的svn:keywords属性设置为LastChangedDate。如果您从以下 URL 使用 HTTP(而不是 Subversion 客户端)检索文件: https ://svn.apache.org/repos/asf/subversion/trunk/INSTALL

您会注意到该文件只有$LastChangedDate$并且没有展开。这是存储在服务器中的文件的表示。从 1.8.0 开始,我们为服务器添加了一个选项,允许 HTTP 客户端请求扩展关键字。因此,如果您访问以下 URL,您将看到关键字已扩展: https ://svn.apache.org/repos/asf/subversion/trunk/INSTALL?kw=1

您还可以使用 Subversion 客户端的cat命令来检索文件并为您执行关键字替换(例如 svn cat https://svn.apache.org/repos/asf/subversion/trunk/INSTALL)。

关键字在展开时展开的值基于文件上次更改的版本的版本属性。版本属性通常在提交时设置(尽管版本属性可能会在以后更改)。因此,您在输出中获得的值取决于扩展完成时的值。该HeadURL属性当然也是如何访问存储库的属性。 Revision可能永远不会改变。

如果您要使用它们,我建议您阅读SVN Book 中关于关键字替换的部分。

于 2013-11-11T04:29:03.483 回答
-1

Subversion 在提交期间设置关键字。尝试一下svn update,看看是否可以解决。

Subversion 关键字替换是一个服务器特性。Subversion 在线手册中有关于它如何工作的文档。确保svn:keywords有您需要的关键字,正确大写,空格分隔,并且没有美元符号。例如

$ svn propset svn:keywords "Revision Author" myfile.txt

并不是

$ svn propset svn:keywords "revision author" myfile.txt     # Wrong capitalization
$ svn propset svn:keywords "$Revision$ $Author$" myfile.txt # $ should not be included
$ svn propset svn:keywords "Revision  Author" myfile.txt    # No commas

而且,现在开始我的咆哮......


RCS 关键字很危险

好吧,他们不会戳你的眼睛。但是,它们并不是那么有用,并且会导致开发中的各种问题。

RCS创建了您看到的当前关键字集。RCS 并没有真正的完整存储库的概念,也没有简单的方法可以查看诸如作者姓名或特定文件的 RCS 修订号之类的信息。关键字将支持这一点。

Subversion 不需要关键字,因为 Subversion 具有竞争存储库的概念。如果您正在编辑一个文件并想知道作者是谁,或者它是什么版本,您只需svn info对该文件进行操作。

但是,旧习惯很难改掉,Subversion 将让您能够支持一些不太糟糕的 RCS 关键字(如果有人在提交注释中输入$Log$单词,它可能会成为递归的噩梦。)因为一些经理(又名无能$Log$奇迹)坚持关键字很重要,如果版本控制系统不支持它们,那就不好了。

那么,使用关键字有什么危害呢?

想象一下你做了一个分支:

$ svn cp trunk/proj ../branches/2.3/proj

现在,稍后,您想查看对该分支所做的更改以及它与主干的不同之处:

$ svn diff $REPO/trunk/proj $REPO/branches/2.3/proj

嗯...看起来该分支上的每个文件都已更改。也许我应该做一个差异...

$ svn diff $REPO/trunk/proj/foo.txt $REPO/branches/2.3/proj/foo.txt

+ /trunk/proj/foo.txt
- /trunk/branches/2.3/proj/foo.txt

+ /* $Revision: 23293$ */
- /* $Revision: 25329$ */

哦...整个差异只是我嵌入在程序中的那个 RCS 关键字。现在,除了那个 RCS 关键字之外,我绝对无法知道哪些文件实际更改了,哪些文件没有更改。

顺便说一句,做一个svn merge,每个关键字更改都会显示为冲突。你将花费 20 分钟来处理这个冲突,这完全是一派胡言,因为当你进行提交时,关键字将再次发生变化。

因此,当您使用 Subversion 时,使用 RCS 关键字几乎没有什么好处,而如果您确实使用它们会很痛苦。

但是,如果我在 Subversion 之外怎么办?

是的,如果您在客户端系统上,RCS 关键字用于确定文件的版本。实际上,RCSident命令可以搜索特定的 $Id$ 字符串。事实上,甚至还有一个特殊的命令ident可以让您快速查看 RCS ID。例如,我想知道我的/bin/ksh:

$ ident /bin/ksh
/bin/ksh
$Id: enum (AT&T Research) 2008-01-08 $
$Id: type (AT&T Labs Research) 2008-01-08 $
$Id: type (AT&T Labs Research) 2008-07-01 $
$Id: test (AT&T Research) 2003-03-18 $
$Id: break (AT&T Research) 1999-04-07 $
$Id: continue (AT&T Research) 1999-04-07 $
$Id: alias (AT&T Research) 1999-07-07 $
$Id: builtin (AT&T Research) 2010-08-04 $
$Id: cd (AT&T Research) 1999-06-05 $
$Id: command (AT&T Research) 2003-08-01 $
$Id: (AT&T Research) 2000-04-02 $
$Id: eval (AT&T Research) 1999-07-07 $
$Id: exec (AT&T Research) 1999-07-10 $
$Id: exit (AT&T Research) 1999-07-07 $
$Id: export (AT&T Research) 1999-07-07 $
$Id: getopts (AT&T Research) 2005-01-01 $
$Id: bg (AT&T Research) 2000-04-02 $
$Id: fg (AT&T Research) 2000-04-02 $
$Id: disown (AT&T Research) 2000-04-02 $
$Id: jobs (AT&T Research) 2000-04-02 $
$Id: hist (AT&T Research) 2000-04-02 $
$Id: kill (AT&T Research) 1999-06-17 $
$Id: let (AT&T Research) 2000-04-02 $
$Id: print (AT&T Research) 2008-11-26 $
$Id: printf (AT&T Research) 2009-02-02 $
$Id: pwd (AT&T Research) 1999-06-07 $
$Id: read (AT&T Research) 2006-12-19 $
$Id: readonly (AT&T Research) 2008-06-16 $
$Id: return (AT&T Research) 1999-07-07 $
$Id: sh (AT&T Research) 93u 2011-02-08 $
$Id: set (AT&T Research) 1999-09-28 $
$Id: shift (AT&T Research) 1999-07-07 $
$Id: sleep (AT&T Research) 2009-03-12 $
$Id: trap (AT&T Research) 1999-07-17 $
$Id: typeset (AT&T Research) 2010-12-08 $
$Id: ulimit (AT&T Research) 2003-06-21 $
$Id: umask (AT&T Research) 1999-04-07 $
$Id: unset (AT&T Research) 1999-07-07 $
$Id: unalias (AT&T Research) 1999-07-07 $
$Id: wait (AT&T Research) 1999-06-17 $
$Id: whence (AT&T Research) 2007-04-24 $
$Id: regex (AT&T Research) 2010-09-22 $
$Id: basename (AT&T Research) 2010-05-06 $
$Id: cat (AT&T Research) 2010-04-11 $
$Id: chmod (AT&T Research) 2010-07-28 $
$Id: cmp (AT&T Research) 2010-04-11 $
$Id: cut (AT&T Research) 2010-08-11 $
$Id: dirname (AT&T Research) 2009-01-31 $
$Id: getconf (AT&T Research) 2008-04-24 $
$Id: head (AT&T Research) 2006-09-27 $
$Id: logname (AT&T Research) 1999-04-30 $
$Id: mkdir (AT&T Research) 2010-04-08 $
$Id: sync (AT&T Research) 2006-10-04 $
$Id: uname (AT&T Research) 2007-04-19 $
$Id: wc (AT&T Research) 2009-11-28 $
$Id: Version JM 93u 2011-02-08 $
$Id: libcoshell (AT&T Research) 2010-05-19 $

是的,这很有帮助...

有多个问题:

  • 一个已编译的程序可能由数十个(如果不是数百个)单独的文件组成。从上面可以看出,在这些中使用 RS 关键字并不是很有帮助。
  • 编译后的代码我优化了ID 字符串。
  • 开发人员必须记住包含它。
  • 即使一切顺利,它也不会告诉你最有用的信息:我在看什么RELEASE 。一个发布可能由多个文件、程序、配置文件等组成。它们相互交互。了解一些 RCS 关键字对您没有多大帮助。您需要整个版本的正式修订号,而不是单个文件。

当您为正式版本进行编译或打包时,您需要一种生成此正式版本的方法。在我们公司,我们使用Jenkins作为我们的持续集成引擎。除非由 Jenkins构建,否则不会向客户发布任何版本。这包括无法编译的 JavaScript 和 Perl 项目。

我们创建了某种类型的构建文件,该文件始终打包在我们的构建中。一个相当简单的可能看起来像这样:

Jenkins Project: %JOB_NAME%
Jenkins Build:   %BUILD_NUMBER%

当 Jenkins 进行构建时,它会设置环境变量JOB_NAMEBUILD_NUMBER. 当我在 Jenkins 上进行构建时,我让 Jenkins 复制并过滤此文件%...%,用实际的 Jenkins 作业替换占位符并构建:在我的 Jenkins 构建之后,文件将如下所示:

Jenkins Project: foo-3.4
Jenkins Build:   233

这可能是我系统上某处的文件,或者我可以嵌入它,因此当用户查看about 框时它会显示出来。这将我的包追溯到正式版本。从该官方版本中,我可以生成发行说明并查看更改了哪些内容。我可以使用标签返回并获取整个项目和所有各种文件以进行测试,以查看可能导致错误的原因。这比随机的 Subversion 修订号更有用。而且,我没有 RCS 关键字在 Subversion 中造成的缺点。

于 2013-11-10T18:18:25.037 回答