简介TwinCAT 3 AdsGitServer 是 Beckhoff 在 TwinCAT 3.1.4024 中集成的 Git 版本控制功能这份 PDF 专门面向自动化工程师讲解如何将 PLC 程序纳入 Git 管理实现多人协同开发、版本回溯与差异对比无需额外安装外部 Git 工具。资料共 1 个 PDF 文件压缩包约 1.77MB内容紧凑适合 PLC 工程师、TwinCAT 开发者及自动化项目团队参考。文档从软硬件准备、路由配置、环境设置讲起完整演示启用 Multiuser、初始化 Git Server、提交与拉取等操作并针对 Init 创建失败、提交多版本冲突等实际问题给出排错建议。此外还涵盖历史版本查看、版本比较、回退当前版本以及第二台 PC 从控制器装载不同版本程序等内容能帮助读者在 TwinCAT 环境内建立一套可用的 PLC 版本管理流程。目前已有 367 人学习下载是快速上手 TwinCAT 内置 Git 功能的实用入门资料。1. 从「上一个能用的版本去哪了」说起AdsGitServer 到底管什么做产线调试的人大概都经历过这种时刻设备运行得好好的你手痒改了段逻辑设备停了想改回去发现昨天那份「能跑」的工程已经被覆盖得连影子都没有。备份文件夹里躺着一堆项目_最终版_真的最终版_v7.zip但谁也不记得 v7 和 v8 差在哪。TwinCAT 3 工程里的 PLC 程序、IO 映射、轴参数全是文本和 XML 结构偏偏这个行业里大多数人还在用压缩包当版本管理工具。AdsGitServer 解决的就是这件事它把 TwinCAT 3 的工程目录放进一个真正的 Git 仓库再通过 ADS 协议把这台工控机上跑的仓库服务暴露给开发端让 TcXaeShell 里的 TwinCAT 工程在开发、调试、发布全过程中都有版本记录可查、可对比、可回滚。这篇笔记按我实际部署和使用的经验把这个服务的原理、初始化、日常操作、高频踩坑和沉淀技巧一次讲透。适合正在被工程版本混乱折磨的电气工程师、上位机开发和设备维护人员。2. 理解 AdsGitServerADS 路由背后的 Git 仓库以及它和 TcXaeShell 源码管理的分工2.1 一个仓库两条路AdsGitServer 在 TwinCAT 3 工程管理里的位置AdsGitServer 这个名字拆开看就很好理解Ads 是 TwinCAT 设备间通讯用的 ADS 协议GitServer 是 Git 的服务器端。合在一起它干的事是让 TwinCAT 的 ADS 通信链路能和 Git 服务共存工控机上哪怕没有图形界面、没有装完整开发环境也能作为 Git 中央仓库运行开发端通过 ADS 路由访问它。我一般把它放在「车间设备侧」这一层。也就是每台设备工控机或者一个工位的工控机本身跑着 TwinCAT 的实时内核同时跑着一个 AdsGitServer 服务这台机器的工程目录由它托管。开发端的 TwinCAT 工程不再直接散落在共享文件夹里而是从这台服务上 clone 下来、改完 push 回去设备现场遇到问题可以现场看版本历史开发端也能远程拿到现场的工程状态。这里要分清楚它的边界AdsGitServer 管的是「仓库在哪、谁能连、版本怎么存」而 TcXaeShell 里那一套源码管理插件管的是「代码怎么提交、怎么对比、怎么合并」两者是一个服务端一个客户端的关系。常见误区是把 Git 的客户端功能和服务端功能混在一起以为装了 Git 就算有版本管理了。真要落地服务端仓库是骨架客户端操作是血肉少了哪边都跑不起来。2.2 为什么不是直接在共享文件夹里放工程很多团队的第一反应是既然 TwinCAT 3 工程是一堆文件和文件夹那我直接在 Windows 共享里建个目录大家把工程放进去不也能多人协作吗。这个思路在只有一个人、一台设备的场景下勉强能用一旦有两个人同时打开同一个工程问题就来了TwinCAT 工程在打开状态下会锁定部分配置文件共享目录里的文件冲突会直接导致工程打开失败更麻烦的是共享文件夹没有版本概念昨天的状态被今天的保存覆盖之后没有任何后悔药可以吃。Git 的模型天生适合这种场景。每次提交都是一次快照文件之间的差异能用文本对比工具看得清清楚楚分支让你在调试现场和稳定版本之间来回切换而不互相污染。AdsGitServer 把 Git 的仓库服务和 TwinCAT 常用的 ADS 网络模型放在一起开发端走到哪只要 ADS 路由能通就能访问到工程仓库不需要把整个工程拷来拷去。还有一层隐性好处是备份。一个 Git 仓库本质上是一个带完整历史的数据目录你可以在服务端写好脚本定期把仓库目录整体复制到 NAS 或者移动硬盘版本历史跟着仓库一起走比备份十几个任意命名的 zip 包可靠得多。2.3 服务端与客户端的典型部署结构实际项目中我惯用的部署方式是一台工控机作为「中央开发仓库」常驻车间办公室这台机器的配置不用高能跑 TwinCAT 3 的 XAE 环境就行重点是硬盘稳定、电源可靠并且接在产线设备同一个局域网里。所有设备终端的工程以这台机器上的仓库为基准版本。开发端笔记本或工位电脑上TwinCAT 工程从仓库 clone 下来日常提交推送都走 Git设备现场的工控机则通过 ADS 与这台服务机通讯需要比对现场实际运行的工程和服务端仓库里的差异时用 TwinCAT 自带的在线对比功能而不是直接覆盖文件。这个结构里有一点需要提前想清楚AdsGitServer 服务的端口和 ADS 路由的端口要能在内网互通。IT 部门如果给工控机开了严格的防火墙策略只放行 PLC 通讯端口Git 走的那条通道会被拦掉表现出来就是开发端能连上 TwinCAT 目标但 clone 不下来工程。遇到这种情况先查端口放行不要急着重装服务。3. 把 AdsGitServer 跑起来环境准备、仓库初始化与最小可用配置3.1 环境准备与前置检查系统服务、ADS 路由、网络端口第一次装 AdsGitServer 时我建议先把环境要素列个清单逐项确认不然会在后续操作里反复翻车。首先是系统层面TwinCAT 3 运行对 Windows 的实时性要求较高服务机不要装多余的杀毒软件和自动更新策略否则后台进程抢 CPU 会导致 TwinCAT 掉到可重配置状态这是车间里最常见的「不知道什么时候发生的玄学故障」之一。其次是 ADS 路由配置。TwinCAT 的开发端要能访问到 AdsGitServer 所在的工控机需要在 TwinCAT 的系统管理器里把目标机器的 AMS NetId 和 IP 地址配置进路由表。实际操作中很多人 clone 工程失败不是 Git 的问题而是 ADS 路由就没通。我习惯先用 TwinCAT 自带的「添加路由」功能做一次目标机连接测试确认路由显示 Active 后再去跑 Git 命令。网络端口方面TwinCAT 3 的 ADS 默认走 48898 端口AdsGitServer 的 Git 服务如果走 HTTP 需要额外监听端口如果走 SSH 则用 SSH 端口。给 IT 报备时把这两类端口一起提不要只说一个。这里有个工程上的细节车间网络里经常有多台工控机AMS NetId 是设备在 ADS 世界的身份证克隆仓库前先确认你连的目标 NetId 对应哪台机器连错了机器拉下来的工程会让你排查到下半夜。3.2 创建并初始化工程仓库最小命令序列环境确认完毕下一步是做仓库初始化。我这里给出一个最小可用的命令序列在服务机上操作时把D:\Repos\line1_cell3换成你自己的仓库根路径。TwinCAT 3 工程里真正的源码是.tsproj项目文件、PLC 的.tpy/.library和各个.xti配置文本等这些都是可以在 Git 里做文本对比的所以仓库不要做成二进制大文件仓库。# 在服务机上创建裸仓库裸仓库是 Git 服务器端的标准形态 git init --bare D:/Repos/line1_cell3.git # 在开发机上把仓库克隆下来得到工作目录 git clone ads-git://工控机IP/Repos/line1_cell3.git D:/Work/line1_cell3 # 查看远程仓库关联信息确认 clone 成功后的远端地址 git remote -v这三条命令看着简单但有三个参数需要注意。--bare一定要带不带的话你会在服务机上得到一个带工作区的普通仓库别人 push 进去会跟你本地的工作区互相冲突出现「远端工作区不一致」的报错这个是我最早踩过的坑。clone 的地址里工控机IP换成实际地址仓库名要和上一步init --bare时的路径对上大小写敏感。git remote -v是检查命令clone 成功后应当能看到 fetch 和 push 两条记录都指向同一个地址如果只有一条或者地址对不上后边提交推不上去时你会很被动。仓库建好后第一次把现有工程纳入版本管理时注意不要把 TwinCAT 正在运行的旧版本文件夹整个拖进去。正确做法是新建一个干净目录把工程文件拷贝进去用 TwinCAT 打开确认编译通过再执行首次提交。这样入库的基线版本是「确定能编译」的状态而不是一堆来路不明的历史残留。3.3 落地一份 .gitignore哪些 TwinCAT 产物不该进仓库TwinCAT 3 工程编译和运行时会生成大量中间文件这些文件如果全部进仓库每次编译后都会出现上百个文件变更真正的代码改动反而被淹没在噪音里。所以 .gitignore 的配置是这个方案里最值得花时间的部分。# 编译输出目录完全不进版本库 _TwinCAT/ bin/ obj/ # 自动生成的类型与配置缓存 *.tmc *.tmc.bak *.tpy # I/O 配置生成的中间产物离散设备和在线状态 *.xti *.xti.bak *.compileinfo # Visual Studio 用户级配置不同人不一样 *.user *.suo # 工程运行时的起动数据与Boot数据 _Boot/ *.boot这份忽略清单里.tmc是从 PLC 工程编译出来的模块配置.tpy是类型库缓存它们在每次编译后都会刷新没有任何历史价值_Boot目录是设备开机自启动时加载的数据跟源码无关。有一点要特别说明.xti文件在某些 TwinCAT 3 版本里包含了部分 IO 映射配置如果你遇到「别人拉下来工程后 IO 全丢了」的问题检查是不是被自己误忽略了不该忽略的文件。我的建议是先按这份模板提交一版然后改一次程序、做一次编译再执行一次git status观察还有没有缓存文件冒出来。有就补充忽略规则直到git status里只剩真正的手动修改。这个过程做完后面所有提交都会干净清爽很多。4. 日常版本管理怎么用提交、分支、标签与回滚的实操姿势4.1 一次规范的提交从「能编译」到「可发布」的提交粒度版本管理工具装好了不等于版本管理就做好了。AdsGitServer 的价值不在于你能提交代码而在于每次提交包含的信息足以让你在三周后想起来「这次改动是干嘛的」。我给自己定过一条规则提交粒度以「能独立编译、逻辑自洽」为最小单位而不是「我今天干的全部活」。一条规则是提交信息必须写清楚「改了什么 为什么改」不要写「update」。比如fix: 修正三号工位回零超时后轴状态未复位的问题这段信息在三个月后翻 log 时一眼就能定位。为了做到这一点我习惯在提交前先用git diff看一眼改动内容确认没有把调试用的临时值混进去。# 提交前先看这次改了哪些文件确认没有缓存文件混进来 git status # 看具体改动内容重点排查是不是只改了目标逻辑 git diff # 按文件提交避免把两个不相关的改动混进同一次提交 git add PLC/Line3/Main.tsvor git commit -m fix: 修正回零超时后轴状态未复位的问题 # 推到服务端仓库让设备现场能拉到这次修复 git push这里划一个重点git add的粒度要小。TwinCAT 工程里一个逻辑改动往往涉及一个 PLC 程序块和一个 IO 配置两个文件改动目的不同就应该分成两次提交。有人图省事git add -A一把梭结果提交历史里全是「改了一堆东西」出问题回滚时根本不知道哪次提交是安全边界。git push别省略只有推到服务端现场设备才有机会同步到这个修复只在本地提交等于没做版本管理。4.2 分支与标签调试现场、发布版本、归档客户交付在车间调试场景里分支的用法和互联网研发不太一样。我常用三个分支角色main是稳定可发布的版本dev是日常开发调试的集散地临时分支按「问题主题」命名比如fix-homing-timeout。现场设备跑的一直是main分支上的某个标签任何未经充分验证的改动都留在dev或临时分支里不许直接推main。标签则是给版本打上的永久记号。设备验收、客户预验收、发货归档这三个节点我都建议打标签。标签名称要带日期和阶段例如release_20250411_acceptance这样现场报问题时你问一句「现在跑的哪个版本」对方报出标签名你就能直接定位到对应的提交。# 从 dev 分支拉出临时修复分支修完再合回 git checkout -b fix-homing-timeout dev # 修复并提交后切回 dev 合并再做一次编译验证 git checkout dev git merge fix-homing-timeout # 已验证稳定切到 main 分支合并并打标签 git checkout main git merge dev git tag -a release_20250411_acceptance -m 三号工位客户预验收版本整个过程里最容易出错的一步是合回main前忘了切换到main。我有一次直接在dev分支上打了发布标签现场clone下来运行后发现带上了一堆没验证完的调试代码设备动作正常但报警信息全是假的地址。从那以后我要求自己打完标签立刻git log --decorate看一眼标签到底挂在哪个提交上。4.3 回滚与对比找回三周前能稳定运行的版本版本管理的最终价值在回滚这一刻体现。设备半夜停机现场工程师说「昨晚就改了一个轴参数」但你不知道具体改在哪这时 AdsGitServer 让你不用靠回忆活着。先查历史再对比差异最后决定是精确挑出一个文件回退还是整个工程回到旧版本。# 查看最近 30 条提交记录找到旧版本所在提交的哈希 git log --oneline -30 # 用标签名直接对比当前工作区和发布版本的差异 git diff release_20250320_acceptance -- PLC/Drive/Axis3.tsvor # 如果确认要整体回到旧版本以它为基础拉出一个恢复分支 git checkout -b restore_20250320 release_20250320_acceptancegit diff是排查现场问题最趁手的工具。轴参数被改没改、改了多少、什么时候改的一次diff全出来了。注意对比时加上具体文件路径TwinCAT 工程文件多整个工程对比的输出即便用文本工具看也费劲精确到文件能省很多时间。git checkout -b而不是直接git checkout是因为你旧的提交可能还包含现场后来验证过的改动直接切过去会把当前的工作成果冲掉。先拉个分支再判断后悔药永远留着。5. AdsGitServer 使用避坑5 个高频踩坑记录5.1 提交后工程打不开文件锁与 .tsproj 权限现象在 TcXaeShell 里关掉工程后执行git pull再打开工程时提示项目文件被占用或损坏工程直接加载失败。原因TwinCAT 工程在打开状态下会保持对.tsproj文件的独占锁而且 XAE 外壳的某些后台进程在界面关闭后并不会立刻释放文件句柄。Git 拉取时遇到锁定的文件会报错但有时候 Git 客户端会先删除旧文件再写入新文件删除遇到锁时留下一个半残状态工程自然打不开。另外检查 .gitignore 是不是把.tsproj误加进去了如果项目文件根本没进仓库pull下来就是个残缺目录。解决工程关闭后等几秒再做 Git 操作实在不行打开任务管理器确认没有残留的 TwinCAT 进程。我现在的习惯是所有pull动作前先确认 XAE 外壳完全退出下载完成后用 TwinCAT 的「恢复项目」功能重新加载一次确认无误再开始改代码。这个步骤看起来繁琐但能省掉大量「工程无端损坏」的排查时间。5.2 合并后 IO 映射全乱XML 结构冲突的真相现象两个人都改了同一个 TwinCAT 工程一个改 PLC 程序一个改了 IO 配置合并后其中一方的 IO 映射丢失设备启动时报变量找不到。原因TwinCAT 3 的 IO 配置分散在多个 XML 和缓存文件里两个人的版本如果基于不同的旧提交Git 合并时无法智能判断 XML 节点的语义只能按行做文本合并。IO 映射这类结构经常被格式化工具重排文本变化大合并结果经常是结构完好的代码和残缺的配置混在一起。解决养成「不同人不同时段改同一个工程」的协作习惯确实需要并行时约定一个人负责 IO 层、另一个人负责 PLC 层提交前先git pull --rebase把对方改动合进来再改。真出现冲突时不要依赖自动合并手动打开.tsproj对照两份历史版本把 IO 节点补齐。合并完成的唯一验收标准是 TwinCAT 能完整激活配置且在线监控变量全部正常而不是「Git 提示冲突已解决」。5.3 服务端仓库「假死」ADS 连接数与 Git 后台进程现象开发端 clone 或 push 时报连接超时但 ADS 通讯是正常的TwinCAT 系统管理器也能连上目标机服务机界面看起来一切正常。原因AdsGitServer 所在工控机长时间开机Git 服务进程或系统网络会话堆积导致新的 Git 连接无法建立某些环境下还有 Windows 服务对连接数上限的限制连接池被占满后表现为「假死」。此时 ADS 走的是另一套端口和通道所以 TwinCAT 连接不受影响。解决在服务机上定时重启 AdsGitServer 服务或者干脆写一个计划任务每天凌晨重启一次。另外把 Git 服务的日志打开出现假死时先看日志尾部有没有大量超时的连接记录有的话把连接等待时间调短让无效连接快速释放。不要一遇到假死就重装服务先重启服务进程观察半小时大多能恢复。5.4 误把备份当版本库单机习惯带到服务端现象某些设备现场因为历史原因保留着「工程_备份_日期」这种目录结构技术人员在服务端顺手也建了这样的目录然后问「为什么我的备份不在 Git 历史里」。原因这本质上是思路没切换过来。AdsGitServer 建的是裸仓库裸仓库里只有版本对象没有你熟悉的工作目录。直接往服务端放一份解压后的工程目录再把这个目录当成 Git 仓库去 clone你会看到历史是空的文件却都在完全没起到版本管理作用。解决服务端只承担仓库职责不要在服务端手动维护工作目录。开发机clone下来的工作目录才是操作现场改动全部通过提交和推送进入版本库服务端的仓库目录不要人工去碰。如果你想给某个状态留档就打标签标签在 Git 里永远可追溯比在文件系统里堆日期目录可靠得多。5.5 符号文件与密文工程版本库里的安全边界现象提交后发现仓库体积暴涨或者客户现场的 PC 里能直接看到 PLC 源程序的明文怀疑版本库被不该看到的人拿到了。原因TwinCAT 工程里除了源码还包含符号文件、配方文件、轴调试参数等敏感数据如果客户交付时整个仓库打包给了现场等于把设备核心逻辑全交出去了。另一个问题是多人共用同一个仓库时源文件的可见范围没人去区分。解决按交付边界拆仓库设备源码仓库和配方参数仓库分开管理客户只能拿到带版本号不带源码的发布目录。符号文件是否入库取决于你需不需要精确追溯历史状态不需要的话和_Boot一起忽略。如果你的工程启用了源代码保护务必确认保护密钥的备份和 Git 仓库分开存放密钥丢了就是整个版本历史全部作废这份风险比仓库本身被盗高得多。6. 把这些技巧沉淀成习惯验证回滚、自动标签与团队协作的收尾建议工具跑通只是开始真正让 AdsGitServer 产生价值的是把它嵌进每天的开发节奏。我现在给自己定了三条雷打不动的习惯。第一条是「每次编译通过必提交」提交信息里写明验证设备是哪个工位、验证结果是什么这样任何一次现场问题都能快速定位到「最近一次验证过的提交」从那里开始排查而不是从头看代码。第二条是「发布必打标签」无论是模拟项目预验收还是现场调试完成标签名统一用release_日期_阶段格式客户问版本时只需要报标签名。第三条是「每周清理一次临时分支」合并进dev的临时分支及时删掉让分支列表保持干净避免几个月后看到一堆不知道还能不能用的旧分支。如果团队不止一个人我在服务机上额外配了一个简单的自动化维护脚本每天凌晨对仓库做一次完整性检查并把仓库目录增量备份到另一块硬盘。脚本逻辑很简单先跑一遍git fsck检查版本库内部一致性再把整个仓库目录用文件同步命令镜像到备份盘。版本历史的容灾能力和源代码本身一样重要仓库盘物理损坏时那份镜像就是你救命的备份。这里有个我交过学费的教训最早部署时我自信地认为既然是服务端仓库错误地只备份了工作目录而不是隐藏的 Git 目录第一次磁盘故障后恢复出来的备份没有完整历史只有文件快照。从那以后备份一律以整个仓库目录为单位先在测试机上恢复一次确认git log能看到全部历史再把这个备份方式定下来。版本管理的本质不是保存文件是保存文件的变化轨迹。这套方案做到位之后最直接的红利是调试现场不再「靠人肉记忆找回滚」。设备出问题拉历史、看差异、挑版本、验证回滚整个链路清晰可控。希望你在接入 AdsGitServer 的过程中能把上面这些参数和习惯直接拿去用少走我走过的弯路。本文还有配套的精品资源点击获取