4. TwinCAT版本控制工具选型

TwinCAT工程并不是单一文本文件,而是一组由多种格式混合构成的工程目录。典型工程根目录下包含 .sln 解决方案文件、.tsproj 系统项目文件、.plcproj PLC 项目文件,以及 POUs/、DUTs/、VISUs/ 等子目录。其中 PLC 的 ST 代码、C++ 源码、部分 XML 描述属于可读文本,而 .tpy、.tcg、.compiled、库文件、编译产物和部分二进制配置则是二进制或半二进制格式。版本控制工具能否高效管理 TwinCAT,关键不在于工具本身“先不先进”,而在于它如何处理这些混合格式、如何处理文件锁、如何处理分支与合并。

先看三种工具在 TwinCAT 场景下的核心差异。Git 是分布式版本控制,每个克隆都是完整仓库,提交在本地完成,分支成本极低,合并能力强,但对二进制文件只能整体替换,无法逐行合并。SVN 是集中式版本控制,支持目录级检出、文件锁和部分检出,对二进制文件的锁定管理更直接,但分支本质是目录拷贝,合并体验较弱。TFVC 是 Team Foundation Version Control,同样是集中式,深度集成 Azure DevOps,支持文件锁、变更集和搁置集,适合已经使用微软 ALM 体系的团队,但跨平台和离线能力弱于 Git。

TwinCAT 工程文件 × 版本控制工具 兼容性对照 TwinCAT 工程文件类型 文本类 .st / .cpp / .xml / .sln 半结构化 .tsproj / .plcproj 二进制类 .tpy / .tcg / 库文件 编译产物 .compiled / _Boot 配置与映射 IO 映射 / 任务配置 库与引用 .library / 引用路径 兼容性矩阵 文件类型 Git SVN TFVC 文本类 优 优 优 半结构化 中 中 中 二进制类 弱 中 中 编译产物 忽略 忽略 忽略 配置映射 中 优 优 库与引用 中 中 中 优 = 可逐行合并 / 中 = 需锁或人工介入 / 弱 = 仅整体替换 忽略 = 应加入 ignore 规则,不纳入版本库 选型依据 团队分布 多地/离线 → Git 集中办公 → SVN/TFVC 二进制占比 高 → 需锁机制 低 → Git 更灵活 分支策略 频繁分支 → Git 线性发布 → SVN/TFVC 现有体系 Azure DevOps → TFVC 开源/自建 → Git 工具链集成 CI/CD 友好度 Git > TFVC > SVN

从矩阵可以看出,三种工具对文本类文件都能胜任,真正拉开差距的是二进制类文件和配置映射。Git 对二进制文件只能整体替换,一旦两人同时修改同一个 .tpy 或库文件,后提交者会直接覆盖前者,且无法通过合并解决。SVN 和 TFVC 支持 svn:needs-lock 或 TFVC 的独占签出,可以在编辑前锁定文件,从机制上避免二进制冲突。因此,如果工程中大量使用库、可视化界面或硬件配置,集中式工具在“防冲突”上更省心;如果工程以 ST 代码和 XML 为主,Git 的分支与合并优势会明显放大。

实际选型时,建议按以下顺序判断。第一步,统计工程中二进制文件的比例。可以在工程根目录执行 git ls-files 或直接查看目录,若 .tpy、.tcg、库文件占比超过三成,应优先考虑带锁机制的 SVN 或 TFVC。第二步,确认团队协作模式。若多人需要同时修改同一 PLC 项目,Git 的“各自分支、最后合并”会频繁在二进制文件上失败,此时应改为“按功能模块拆分工程”或改用集中式锁。第三步,评估现有工具链。若团队已使用 Azure DevOps 的 Boards、Pipelines,TFVC 的集成成本最低;若已使用 GitLab、GitHub 或 Jenkins,Git 更自然。第四步,考虑离线与审计要求。Git 支持完整离线提交和历史追溯,SVN/TFVC 的提交必须联网,但集中式日志更便于统一审计。

一个常见的折中方案是:用 Git 管理 ST 代码、C++ 源码和 XML 配置,用 SVN 或 TFVC 单独管理二进制库与硬件配置,或者将二进制文件放入 Git LFS。但 TwinCAT 的 .tpy 等文件并不总是适合 LFS,因为 LFS 只解决存储,不解决合并冲突,仍需配合“一人一锁”的流程约定。

下面给出一份可直接用于团队讨论的选型决策表。表中“权重”由团队根据自身情况填写,分值 1~5,加权总分最高者优先。示例中假设某团队有 6 名工程师、2 个异地办公点、工程中二进制文件约占 25%、已使用 GitLab。按此假设,Git 加权得分 4.15,SVN 3.30,TFVC 2.85,因此推荐 Git,并配合“二进制文件修改前在群里声明”的轻量锁约定。

评估维度 权重 Git 得分 SVN 得分 TFVC 得分
文本文件合并能力0.20544
二进制文件防冲突0.25255
分支与发布灵活性0.20523
离线与异地协作0.15522
现有工具链集成0.20432
加权总分1.004.153.302.85

无论选择哪种工具,都必须先建立 .gitignore 或对应的忽略规则。TwinCAT 工程中应忽略 _Boot/、_CompileInfo/、*.compiled、*.tpy 的临时副本以及 bin/、obj/ 等编译输出。若使用 Git,可在仓库根目录放置如下忽略文件:

# TwinCAT 编译产物与临时文件
_Boot/
_CompileInfo/
*.compiled
*.tpy.bak
*.tcg.bak
bin/
obj/
# 本地用户设置
*.tpr
*.tws

需要特别说明的是,.tpy 文件是否纳入版本控制,取决于团队是否把它当作“源文件”。如果 .tpy 是由库安装生成的,应忽略;如果是工程中手工维护的库描述,则应纳入,但必须配合锁机制。判断方法很简单:在干净环境中重新克隆或检出后,执行一次完整编译,若缺少该文件会导致编译失败,则它属于源文件;若编译能自动生成,则属于产物,应忽略。

不要用“先提交再回滚”的方式处理二进制冲突。Git 在二进制文件冲突时不会生成合并标记,只会保留一方版本,回滚后另一方的修改可能已经丢失。正确做法是:修改二进制文件前先锁定或声明,提交时附上变更说明,并在合并前用 TwinCAT 的“比较工程”功能人工确认差异。

最后给出一个可执行的落地检查清单,用于选型后验证配置是否正确。第一,在干净目录克隆或检出工程,确认能直接打开 .sln 并编译通过。第二,故意修改一个 ST 文件并提交,确认历史中能看到逐行差异。第三,模拟两人同时修改同一个 .tpy,确认所选工具能阻止或明确提示冲突,而不是静默覆盖。第四,检查忽略规则是否生效,确认 _Boot/ 和 *.compiled 没有进入版本库。第五,在 CI 中执行一次编译,确认版本控制中的文件足以还原完整工程。完成这五步,说明工具选型与工程配置已经匹配,后续再根据团队规模变化调整锁策略或分支模型即可。