使用 git-svn 时模拟 subwcrev

Posted

技术标签:

【中文标题】使用 git-svn 时模拟 subwcrev【英文标题】:Emulate subwcrev when using git-svn 【发布时间】:2010-12-29 13:42:04 【问题描述】:

我使用 git-svn 与包含一些 C++ 项目的现有 SVN 存储库进行交互。 subwcrev.exe 用作预构建事件以更新 C++ 标头 (svnversion.h) 中的某些字符串。这些字符串被硬编译为生成的二进制文件形成一些版本信息。

由于 subwcrev 需要 .svn 元数据才能工作,因此在 git-svn 工作副本上使用预构建事件将失败。所以我想出了以下 bash 脚本,我将其用作我的 git 存储库的提交后和签出后挂钩。该脚本尝试根据 git svn info 的输出(缓存在本地文件中)执行与 subwcrev 相同的操作。

#!/bin/sh
if [ ! -f svninfo ] ; then
    git svn info > svninfo
fi

revision=`sed -e "/Revision/!d" -e "s/Revision: \(.*\)/\1/" svninfo`
lastchange=`sed -e "/Last Changed Rev/!d" -e "s/Last Changed Rev: \(.*\)/\1/" svninfo`
# Get the last changed date, extract timestamp, replaces dashes with slashes
changedate=`sed -e "/Last Changed Date/!d" -e "s/Last Changed Date: \(.\19\\).*/\1/" -e "s!-!\\\\\\/!g" svninfo`
now=`date "+%Y\/%m\/%d %H:%M:%S"`

gitcommit=`git show --abbrev-commit | sed -n -e "s/commit //p"`

for entry in $( find -name svnversion_template.h ); do
    newname=`echo $entry|sed -e "s/_template//"`
    sed -e "s/\\\$WCRANGE\\\$/$revision/" \
        -e "s/\\\$WCREV\\\$/$lastchange-$gitcommit/" \
        -e "s/\\\$WCDATE\\\$/$changedate/" \
        -e "s/\\\$WCNOW\\\$/$now/" \
        -e "s/\\\$WCURL\\\$/local git repo/" \
        -e "s/\\\$WCMODS.*\\\$/(true)/" \
        -e "s/\\\$WCMIXED.*\\\$/(false)/" \
        $entry > `echo $entry|sed -e "s/_template//"`
done

到目前为止,我无法真正模仿的是自动检测本地未提交的更改(基于上次签出的 SVN 修订版),这使得 subwcrev 非常有用。

我将 $WCREV$ 替换为 SVN 存储库的修订号(就像 subwcrev 所做的那样),但这次我添加了我的缩写 git commit hash 来识别我编译的代码。我现在的问题是:有没有办法在 shell 脚本中区分我当前的 HEAD 是否与上次获取的 SVN 版本不同,以便我可以省略添加 -$gitcommit 部分并将 $WCMODS$ 设置为 false?

如果有类似post-"git svn dcommit" 钩子的东西,我的问题也会得到解决,因为那个特殊的钩子会以不同的方式创建 svnversion.h。可以以某种方式添加这样的钩子吗?

【问题讨论】:

【参考方案1】:

我不是很明白你的观点,但先开始改进你的脚本。

revision=$(grep -Po "(?<=Revision: ).*" svninfo)
lastchange=$(grep -Po "(?<=Last Changed Rev: ).*" svninfo)
# Get the last changed date, extract timestamp, replaces dashes with slashes
changedate=$(grep -Po "(?<=Last Changed Date: ).19" svninfo)
changedate=$changedate//-//
now=$(date "+%Y\/%m\/%d %H:%M:%S")

那么,在for循环中,您能否详细解释一下,您需要什么结果? 你能展示一份 svnversion_template.h 的样本吗?

【讨论】:

【参考方案2】:

所以看起来您可能必须自己解析git svn info 查询的内容才能获得通常存储在 WCREV 中的内容。对我来说,示例结果如下所示:

git svn info
Path: .
URL: http://myurl.com/trunk/myrepo
Repository Root: http://myurl.com
Repository UUID: 15fed3e9-81ce-ef4a-a7da-fc36e3df1edc
Revision: 14106
Node Kind: directory
Schedule: normal
Last Changed Author: myusername
Last Changed Rev: 14106
Last Changed Date: 2015-05-29 10:23:10 -0400 (Fri, 29 May 2015)

现在对于您问题的第二部分,您是否可以判断您的 git HEAD 是否与最新的 svn checkout 匹配,您需要使用命令 git diff git-svn 命令。这里的“git-svn”是git-svn程序正在维护的分支的名称,如果一切都是最新的,结果将为空。

【讨论】:

以上是关于使用 git-svn 时模拟 subwcrev的主要内容,如果未能解决你的问题,请参考以下文章

git-svn 使用啥 svn 客户端?

git-svn 的钩子

Linux实用命令之git-svn

如何解决与 git-svn 的冲突?

git-svn 使用方式

如何在 git-svn 中设置上游分支?