最有效、最不可绕过的控制方式是直接在服务端用pre-commit hook做正则拦截,它不依赖客户端是否安装插件或自觉填写,只要提交就立刻校验并拒绝;需重点拦截纯标点/空白、模糊词单独出现、模板占位符未替换、重复字符堆砌及仅含URL无描述等影响追溯的硬伤。

直接在服务端用 pre-commit hook 做正则拦截,是最有效、最不可绕过的控制方式。它不依赖客户端是否安装插件或是否自觉填写,只要提交动作发生,就立刻校验、立刻拒绝。
明确要拦截的低级错误类型
不是所有“不好看”的日志都要拦,重点拦真正影响追溯和协作的硬伤。常见需正则匹配拦截的包括:
- 纯标点或空白字符(如 “。”、“——”、“ ”)
- 通用模糊词(如 “update”、“fix”、“修改”、“ok”,单独出现且无上下文)
- 模板占位符未替换(如 【修改内容】: 后面为空或仍是原文)
- 重复字符堆砌(如 “aaaaaa”、“111111”,长度 ≥6 且无字母/数字混合)
- 仅含 URL 或邮箱但无描述(如只写 “https://jira.xxx/ABC-123”)
PowerShell 脚本示例(VisualSVN Server 推荐)
将以下逻辑写入 Pre-commit Hook(.ps1 文件),注意路径和编码需匹配你的环境(推荐 UTF-8 + BOM):
$REPOS = $args[0]
$TXN = $args[1]
$log = & "$env:VISUALSVN_SERVER\bin\svnlook" log "$REPOS" -t "$TXN"
<h1>拦截:全空格、纯标点、少于4个有效字符</h1><p>if ($log -match '^[[:punct:]\s]*$' -or $log.Trim().Length -lt 4) {
Write-Host "❌ 提交被拒:日志不能全为标点或空白,请填写具体变更说明" -ForegroundColor Red
exit 1
}</p><h1>拦截:常见模糊词单独出现(前后非字母/数字)</h1><p>$blurWords = @('update', 'fix', '修复', '修改', 'ok', 'done', 'test')
foreach ($word in $blurWords) {
if ($log -match "(?<![a-zA-Z\u4e00-\u9fa5])$word(?![a-zA-Z\u4e00-\u9fa5])") {
Write-Host "❌ 提交被拒:‘$word’属于模糊描述,请补充具体修改点" -ForegroundColor Red
exit 1
}
}</p><h1>拦截:模板字段未填写(例如【修改内容】: 后无实质文字)</h1><p>if ($log -match '【修改内容】:\s<em>(?:$|[\s ]</em>(?:【|\z))') {
Write-Host "❌ 提交被拒:【修改内容】字段不能为空或仅含空格" -ForegroundColor Red
exit 1
}</p><h1>拦截:连续相同字符 ≥6 个(防偷懒输入)</h1><p>if ($log -match '([a-zA-Z0-9])\1{5,}') {
Write-Host "❌ 提交被拒:禁止使用重复字符(如 aaaaaa、111111)代替有效描述" -ForegroundColor Red
exit 1
}关键配置细节提醒
正则生效的前提是细节到位,容易忽略但直接影响成败:
- 脚本必须保存为 UTF-8 with BOM 编码,否则中文正则会失效(PowerShell 默认 ANSI)
- svnlook 路径务必准确,VisualSVN 默认在 E:\VisualSVN_Server\bin\svnlook.exe,不要硬写 C:\Program Files
- 权限需赋予执行权:右键脚本 → 属性 → 安全 → 给 “NETWORK SERVICE” 用户读取+执行权限
- 测试务必用真实提交触发:不能只运行脚本,要用 TortoiseSVN 提交一个违规日志来验证拦截效果
- 首次上线建议先 warn 再 block:把 exit 1 改成 Write-Warning + exit 0,观察一周再切为强制拦截
配合客户端模板提升成功率
服务端拦截是兜底,但体验更好是“让人不想犯错”。建议同步配置 tsvn:logtemplate 属性:
- 模板用【】包裹必填字段,视觉强提示
- 提交类型枚举写成 【提交类型】: 功能新增|BUG修复|代码优化,减少自由输入
- 在【修改内容】后加注释:(请说明改了哪几个文件、解决什么问题)
- 模板提交进 SVN,全团队自动同步,无需每人手动设置

















