使用cvs2git转换CVS到Git,优雅解决“Multiple definitions of the symbol”错误
CVS转Git时cvs2git报重复符号定义的问题解决
问题场景
使用cvs2git 2.5.0转换CVS仓库到Git,执行命令:
cvs2git --blobfile=git-stage/git-blob.dat --dumpfile=git-stage/git-dump.dat --keep-cvsignore --retain-conflicting-attic-files --encoding=ascii --encoding=utf8 --encoding=utf16 --fallback-encoding=utf8 cvsroot
运行后出现大量如下错误:
ERROR: Multiple definitions of the symbol 'MYSYM' in 'cvsroot/path/filename1,v': 1.1.1.1 1.1.1 ERROR: Multiple definitions of the symbol 'MYSYM' in 'cvsroot/path/filename1,v': 1.1.1.1 1.1.1 ERROR: Multiple definitions of the symbol 'MYSYM' in 'cvsroot/path/filename2,v': 1.1.1.1 1.1.1 ...
查看报错的CVS文件(filename1,v)开头,发现符号行存在重复定义:
head 1.1; branch 1.1.1; access ; symbols MYSYM:1.1.1.1 MYSYM:1.1.1; locks ; strict; comment @# @; ...
疑问解答
1. 这种重复符号定义是什么,为何广泛存在?
- 重复符号定义是指CVS文件的
symbols行中,同一个符号(这里是MYSYM)被绑定到了两个不同的版本号(1.1.1.1是vendor分支的版本,1.1.1是主分支的分支节点)。 - 广泛存在的原因通常是早期CVS操作不规范:
- 手动编辑过CVS的
,v文件,误添加了重复符号; - 使用了存在bug的批量标签/分支工具,导致符号重复绑定;
- 合并vendor分支或其他分支时的误操作,触发了符号重复写入。
- 手动编辑过CVS的
2. 为何cvs2git无法处理,--retain-conflicting-attic-files参数无效?
- cvs2git对CVS仓库的结构校验非常严格,重复符号违反了CVS的规范(一个符号应当唯一对应一个版本),因此会直接报错终止转换。
--retain-conflicting-attic-files参数的作用是处理Attic目录中存在冲突的文件(比如文件被删除后重新添加导致的同名文件冲突),和符号重复定义属于完全不同的问题场景,因此该参数对当前报错无效。
3. 是否有优雅的解决方案?
推荐以下几种方案:
方案1:用cvs2git自定义脚本过滤重复符号
cvs2git支持通过--options参数加载Python脚本,自定义处理逻辑。可以编写脚本过滤重复的符号定义,示例如下:
# 保存为cvs2git_options.py def filter_symbol(symbol_name, symbol_version, cvs_file): # 针对MYSYM符号,只保留指定版本 if symbol_name == 'MYSYM': # 过滤掉1.1.1版本,保留1.1.1.1 if symbol_version == '1.1.1': return None return (symbol_name, symbol_version) # 注册过滤器 from cvs2git import main main.SymbolFilter = filter_symbol
执行转换时加上--options参数:
cvs2git --options=cvs2git_options.py --blobfile=git-stage/git-blob.dat --dumpfile=git-stage/git-dump.dat --keep-cvsignore --encoding=ascii --encoding=utf8 --encoding=utf16 --fallback-encoding=utf8 cvsroot
方案2:批量修复CVS仓库的,v文件
用sed或awk批量处理所有存在重复符号的,v文件,删除重复的符号定义。例如,针对MYSYM的重复定义,可以用以下sed命令批量修复:
# 先测试输出,不修改文件 find cvsroot -name "*.v" -exec sed -n 's/\(MYSYM:[0-9.]*\) \1/\1/p' {} \; # 确认无误后执行修改 find cvsroot -name "*.v" -exec sed -i 's/\(MYSYM:[0-9.]*\) \1/\1/' {} \;
如果需要更通用的符号去重,可以用awk脚本:
find cvsroot -name "*.v" -exec awk ' /^symbols/ { split($0, parts, "symbols "); split(parts[2], syms, " "); seen = {}; new_syms = ""; for (s in syms) { split(syms[s], kv, ":"); if (!seen[kv[1]]) { seen[kv[1]] = 1; new_syms = new_syms " " syms[s]; } } print "symbols" new_syms ";"; next; } 1' {} > {}.tmp && mv {}.tmp {} \;
方案3:尝试其他转换工具
如果cvs2git的严格校验难以绕过,可以试试git cvsimport命令,它对不规范的CVS仓库兼容性更好,虽然功能不如cvs2git完善,但能完成基础转换:
git cvsimport -d cvsroot -A authors.txt -k -m -o master module_name
内容的提问来源于stack exchange,提问作者Yogesh Devi
相关产品推荐
相关产品推荐

