我有一个中等大小的存储库(大约 2500 个版本),来自我过去 3 年一直在运行的一个项目。那里有一个特定的文件(我们称之为 foo.xml),我现在想分析它的演变。理想情况下,我想要的是将该文件的所有版本导出到一个目录中,并附加日期,例如
2007_08_08_foo.xml
2007_08_09_foo.xml
2007_08_15_foo.xml
...
实现这一目标的最快方法是什么?
答案1
我认为 SVN 没有内置该功能,但如果您能够在保存 SVN 存储库的服务器上运行命令(并假设该服务器具有可用的标准 UNIX/Linux 工具),则这个 bash 脚本应该可以为您完成此操作:
REPOS=/path/to/repos
FILE=dir/foo.xml
for rev in "$(svnlook history $REPOS $FILE | awk 'NR > 2 { print $1 }')"; do
rev_date=$(svnlook date -r $rev $REPOS | awk '{ print $1 }')
svnlook cat -r $rev $REPOS $FILE > ${rev_date}_${FILE}
done
这将生成以下形式的文件名2007-08-08_foo.xml
。当然,您必须将/path/to/repos
第一行更改为存储库的实际文件系统路径(而不是 URL),并将dir/foo.xml
第二行更改为存储库内文件的路径。
如果日期中的下划线对您来说确实很重要,请将第 4 行更改如下:
rev_date=$(svnlook date -r $rev $REPOS | awk '{ print $1 }' | tr - _)
还要记住,如果文件在某一天被修改了多次,那么只有每天的第一次编辑才会真正反映在写入的文件中。
答案2
我的同事出于类似目的编写了这个 shell 脚本:
/bin/bash #!/bin/bash 对于 `svn log $1 | grep ^r[0-9] | cut -c 2- | cut -d ' ' -f 1` 中的 rev;执行 svn日志-r $ rev svn diff -r $[$rev-1]:$rev $1 2>/dev/null || svn cat -r $rev $1 完毕
您不需要服务器访问权限即可运行它;在您已签出该文件的目录中运行它并传递文件名作为参数。您可能希望修改循环主体以写入完整文件,而不是将差异打印到 stdout:
做 svn cat -r $rev $1 > $1.$rev 完毕
答案3
我在使用此答案中的一个脚本时遇到了问题,只要文件名中有空格,它似乎就不起作用。我不是 Bash 脚本方面的高手,但这是一个快速的解决方案。
#!/bin/bash
echo "svn log \"$1\" | grep ^r[0-9] | cut -c 2- | cut -d ' ' -f 1"
for rev in `svn log "$1" | grep ^r[0-9] | cut -c 2- | cut -d ' ' -f 1`; do
svn log -r $rev
#svn diff -r $[$rev-1]:$rev $1 2>/dev/null || svn cat -r $rev $1
`svn cat -r $rev "$1" > "$rev.$1"`
done
答案4
如果您使用的是 Windows,这可能会有所帮助。文件名应该是脚本的一个参数。让它成为您自己的。
=== 获取-SvnFileHistory.ps1
$Filename = "C:\path\to\workingcopy\file\thefile.txt"
& svn log "$Filename" |
Select-String -pattern '^r(\d+) ' |
ForEach-Object {
if ($_ -match '^r(\d+).*') {
& svn ls -v -r $Matches[1] "$Filename"
}
}
从 PowerShell 控制台提示符或 cmd.exe 提示符运行它:
powershell -NoLogo -NoProfile -File "C:\path\to\script\Get-SvnFileHistory.ps1"