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

用git-SVN处理SVN关键字扩展,svn,git,version-control,Svn,Git,Version Control,我最近询问了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之外的所有SV

我最近询问了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属性”


但是,用几个提交前/提交后挂钩来模拟这个关键字似乎并不太棘手。我是第一个想要这个的人吗?有人有这样做的代码吗?

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

$Id: deadbeefdeadbeefdeadbeefdeadbeefdeadbeef$

其中,
deadbeef…
是对应于该文件的blob的sha1。如果您确实需要该关键字扩展,并且需要在git repo中使用它(与导出的归档相反),我认为您必须使用
ident
git属性和一个自定义脚本来为您进行扩展。仅仅使用钩子的问题是,工作树中的文件与索引不匹配,git会认为它被修改了。

这里发生了什么: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关键字,您可能需要从这个开始。基本上,
$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
clean
命令中无法使shell转义正常工作,只需编写自己的Perl脚本,分别用于扩展和删除RCS关键字,并将这些脚本用作过滤器

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

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

事实并非如此$日期$等扩展到签入时保留的值。无论如何,这是非常有用的。因此,它不会在其他修订或分支上更改,除非该文件实际上已重新检入。 从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过滤器)是不正确的。它插入签出的时间/日期,或导致签出运行的任何内容。

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


它的设置并不像人们希望的那么简单,但它似乎可以工作。它使用了一个用perl编写的污迹/干净过滤器对(类似于emk的答案所描述的),是的,它将使用.gittattributes中设置的扩展名来处理所有文件,通常会稍微降低速度

这个“git描述”的东西可以作为正常git操作的一部分透明地运行吗?我们无法可靠地期望git命令在Hudson实例中可用。@Thorbjørn Ravn Andersen,我对Hudson不太熟悉,但是如果您的Hudson实例没有git的副本,那么其他系统必须运行git来生成源代码的签出。使用该系统运行git Descripte。我不确定这是否有帮助。我最终使用了jGit——它支持“rev parse HEAD”,但非常安静。