使用git-svn处理SVN关键字扩展

使用git-svn处理SVN关键字扩展

Dealing with SVN keyword expansion with git-svn

最近,我问到有关Git中关键字扩展的问题,我愿意接受这种设计,而不是真的在Git中支持该想法。

不管是好是坏,我目前正在研究的项目都需要像这样的SVN关键字扩展:

1
svn propset svn:keywords"Id" expl3.dtx

使此字符串保持最新:

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

但是我很想使用Git进行版本控制。 不幸的是,根据文档,git-svn不支持此功能:

"We ignore all SVN properties except svn:executable"

但是用几个前后提交钩子来模拟这个关键字似乎并不难。 我是第一个想要这个的人吗? 有人有一些代码可以做到这一点吗?


这是怎么回事:Git经过优化,可以尽快在分支之间切换。特别地,git checkout被设计为不触摸两个分支中相同的任何文件。

不幸的是,RCS关键字替换打破了这一点。例如,使用$Date$要求git checkout在切换分支时触摸树中的每个文件。对于像Linux内核那样大小的存储库,这将使一切陷入停顿。

通常,最好的选择是标记至少一个版本:

1
$ git tag v0.5.whatever

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

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

在这里,git告诉我我正在使用匿名版本6提交超过v0.5.15.1的版本,并且SHA1哈希以g61cde1d开头。如果将此命令的输出粘贴到某个地方的*.h文件中,则表示您在工作,并且将发行的软件链接回源代码也没有问题。这是首选的处理方式。

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

但是,如果您绝对不能避免使用RCS关键字,那么以下内容将帮助您入门:

1
2
3
4
5
6
7
8
9
10
11
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

在我的系统上,我得到:

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

如果在smudgeclean命令中无法使外壳转义起作用时,只需编写您自己的Perl脚本来分别扩展和删除RCS关键字,然后将这些脚本用作过滤器即可。

请注意,您确实不希望对超出绝对必要数量的文件进行更多操作,否则git将失去其大部分速度。


Unfortunately, RCS keyword
substitution breaks this. For example,
using $Date$ would require git
checkout to touch every file in the
tree when switching branches.

那是不对的。 $ Date $等扩展为在签入时保存的值。无论如何,这是有用的。因此,除非实际重新检入文件,否则它在其他修订版或分支上不会更改。
从RCS手册中:

1
2
3
   $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过滤器的答案是错误的。它插入结帐的时间/日期,或导致结帐运行的任何时间。


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

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

它的设置并不像人们想要的那么简单,但是它似乎可以工作。它使用用perl编写的污迹/干净过滤器对(类似于emk的答案),是的,它将触摸所有扩展名为.gitattributes的文件,通常会降低速度。


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

1
$Id: deadbeefdeadbeefdeadbeefdeadbeefdeadbeef$

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


推荐阅读