43

我最近询问了Git 中的关键字扩展,我愿意接受在 Git 中不真正支持这个想法的设计。

无论好坏,我目前正在从事的项目需要像这样的 SVN 关键字扩展:

svn propset svn:keywords "Id" expl3.dtx

保持这个字符串是最新的:

$Id: expl3.dtx 803 2008-09-11 14:01:58Z will $

但是我很想用 Git 来做我的版本控制。不幸的是,根据文档, git-svn 不支持这一点:

“我们忽略除 svn:executable 之外的所有 SVN 属性”

但是通过几个 pre/post 提交钩子来模拟这个关键字似乎并不太棘手。我是第一个想要这个的人吗?有没有人有一些代码来做到这一点?

4

4 回答 4

42

这里发生了什么:Git 经过优化,可以尽快在分支之间切换。特别是,git checkout旨在不触及两个分支中相同的任何文件。

不幸的是,RCS 关键字替换打破了这一点。例如,使用$Date$将需要git checkout在切换分支时触摸树中的每个文件。对于 Linux 内核大小的存储库来说,这将使一切戛然而止。

一般来说,最好的办法是标记至少一个版本:

$ git tag v0.5.whatever

...然后从您的 Makefile 中调用以下命令:

$ git describe --tags
v0.5.15.1-6-g61cde1d

在这里,git 告诉我,我正在处理 v0.5.15.1 之后的匿名版本 6 提交,SHA1 哈希以g61cde1d. 如果您将此命令的输出粘贴到某个*.h文件中,那么您就是在做生意,并且将已发布的软件链接回源代码不会有任何问题。这是做事的首选方式。

如果您无法避免使用 RCS 关键字,您可能需要从Lars Hjemli 的解释开始。基本上,$Id$很简单,如果你使用git archive,你也可以使用$Format$.

但是,如果您绝对无法避免使用 RCS 关键字,那么以下内容应该可以帮助您入门:

git config filter.rcs-keyword.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'
git config filter.rcs-keyword.smudge 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date: `date`\\\$/"'

echo '$Date$' > test.html
echo 'test.html filter=rcs-keyword' >> .gitattributes
git add test.html .gitattributes
git commit -m "Experimental RCS keyword support for git"

rm test.html
git checkout test.html
cat test.html

在我的系统上,我得到:

$Date: Tue Sep 16 10:15:02 EDT 2008$

smudge如果您无法在and命令中使用 shell 转义符clean,只需编写您自己的 Perl 脚本来分别扩展和删除 RCS 关键字,并将这些脚本用作您的过滤器。

请注意,您真的不想对超过绝对必要的文件执行此操作,否则 git 将失去大部分速度。

于 2008-09-16T14:25:23.437 回答
24

不幸的是,RCS 关键字替换打破了这一点。例如,使用 $Date$ 将需要 git checkout 在切换分支时触摸树中的每个文件。

那不是真的。$Date$ 等扩展为在签入时持有的值。无论如何,这更有用。所以它不会在其他修订版或分支上更改,除非该文件实际上被重新签入。从 RCS 手册:

   $Date$ The  date  and  time the revision was checked in.  With -zzone a
          numeric time zone offset is appended;  otherwise,  the  date  is
          UTC.

这也意味着上面使用 rcs-keyword.smudge 过滤器的建议答案是不正确的。它插入结帐的时间/日期,或任何导致它运行的内容。

于 2009-07-28T14:04:11.107 回答
6

这是一个示例项目,其中包含向 git 项目添加 RCS 关键字支持所需的配置和过滤器代码:

https://github.com/turon/git-rcs-keywords

It's not as simple to setup as one would like, but it seems to work. It uses a smudge/clean filter pair written in perl (similar to what emk's answer described), and yes, it will touch all files with the extensions set in .gitattributes, generally slowing things down a bit.

于 2011-04-12T09:36:14.330 回答
1

您可以在文件上设置 ident 属性,但这会产生类似的字符串

$Id: deadbeefdeadbeefdeadbeefdeadbeefdeadbeef$

deadbeef...与该文件对应的 blob 的 sha1 在哪里。如果您确实需要该关键字扩展,并且在 git 存储库中需要它(而不是导出的存档),我认为您将不得不ident使用带有自定义脚本的 gitattribute 来为您进行扩展。仅使用钩子的问题是工作树中的文件与索引不匹配,git 会认为它已被修改。

于 2008-09-15T12:16:30.790 回答