简介: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. 理解 AdsGitServer:ADS 路由背后的 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 的过程中,能把上面这些参数和习惯直接拿去用,少走我走过的弯路。
本文还有配套的精品资源,点击获取