TwinCAT AdsGitServer 初始化失败与双机协同排障

发布时间:2026/10/28 3:53:42
TwinCAT AdsGitServer 初始化失败与双机协同排障

简介:《TwinCAT 3 AdsGitServer的使用》是一份面向自动化技术与PLC开发人员的PDF技术文档,聚焦在TwinCAT 3.1.4024及以上环境中直接使用集成Git功能进行版本管理,解决协同开发中提交、拉取、差异查看与历史回退等需求。压缩包内仅含1个PDF文件,大小约1.77MB,内容以操作说明和问题排查为主,篇幅紧凑,便于随查随用。已有373人学习,具备一定参考热度。文档围绕Multiuser启用、Git Server初始化、常规操作界面以及Init创建失败、双版本提交等常见问题展开,并涉及历史版本查看、版本比较、恢复指定版本及第二台PC装载不同版本PLC程序等场景,可帮助读者理解控制器作为Git Server的工作方式,并积累PLC协同开发中的排错思路。

1. 点下 Init local and Remote 之后一片安静:这类「连不上仓库」的坑有多常见

在 TwinCAT 3 AdsGitServer 的现场支持里,我遇到最多的不是 Git 命令不会敲,而是「Multiuser Explorer 里点 Init local and Remote,什么都没发生」——弹窗一闪而过、Multiuser Repository 的 URL 一直空白、或者干脆提示初始化失败,控制器上连仓库文件夹都没建出来。这类故障看着像玄学,实际都落在三个可验证的点上:ADS 路由通不通、控制器侧的 Git 服务起没起、本地和远端有没有上一轮留下的残留。版本管理一旦卡在第一步,后面的提交、比对、回退全都无从谈起。下面按「初始化失败 → 提交与回退异常 → 双机协同冲突」的顺序拆开,每一步都给能直接抄的排查命令和参数。

2. 初始化就翻车:Init local and Remote 失败的四个现场与根因

Init 这一步是整个流程的地基,它要做的事情其实很直白:在开发 PC 的 PLC 项目目录下建一个本地 Git 仓库,在控制器侧的仓库目录下建一个同名远端仓库,然后把两边关联起来。任何一环没对齐,表现出来都是同一个结果——界面没反应或者报初始化失败,但根因可能完全不同,所以别一上来就重装软件,先分清是哪一类。

2.1 URL 空白不是 Bug:ADS Route 与仓库名的生成逻辑

最常见的「疑似故障」是:ADS Route 下拉框已经选好了控制器,Multiuser Repository 名称也填了,但下面那个 URL 输入框死活是空的,于是有人以为路由断了,反复重启。这个 URL 并不是实时计算的,它是「选中的 ADS 路由 + 仓库名」拼出来的字符串,只有输入框的变更事件被触发时才会刷新一次。

所以处理办法非常土但有效:把仓库名最后一个字符删掉,再手动补回去,光标离开输入框,URL 立刻就会生成。这个动作本质上就是强制触发一次刷新。

真正需要警惕的是另一种情况——删了补、补了删,URL 依然是空的。这时候才轮到怀疑 ADS 路由本身:路由是不是加在了另一台控制器上、控制器 IP 是否变过、路由表里的地址和实际设备是否还对应。验证顺序我一般是这样:

# 开发 PC 上以管理员身份运行,先确认两个服务都在 Running Get-Service | Where-Object { $_.Name -match 'TwinCAT' } | Select-Object Name, Status, StartType

这里关键看两行:TwinCAT 3 System Service 和 TwinCAT3 AdsGitServer。前者没起来,整个 TwinCAT 环境都是死的;后者没起来,路由能通、PLC 能登录,但 Git 仓库操作会失败——这也是最容易被忽略的一种「半通」状态。StartType 那一列如果显示 Disabled,说明有人手工关过,改成 Automatic 再启动。

仓库名本身也有讲究,它将来就是控制器上仓库目录下的文件夹名,尽量用英文、数字和下划线,别带空格和中文,避免在路径拼接时出现意外的转义问题。

2.2 Init 失败先清残留:Local、Remote 与 Boot 三处要一起清

第二种高频现场是:以前在这台控制器上做过版本管理,换了个新 PLC 项目再点 Init,直接失败。根因不在新项目,而在旧项目的残留。Git 的判断依据是「这里已经有一个仓库了」,它不会管这个仓库属于谁。

要清的地方有三处,少清一处都会复发:

第一处是开发 PC 上本地 PLC 项目目录里的 Git 痕迹,也就是那个 .git 文件夹和几个配套的配置文件。它们通常藏在项目根目录下,资源管理器默认不显示。

第二处是控制器上 TwinCAT 运行时的 Boot 目录内容。Boot 里存的是当前加载的 PLC 程序,只要它还有内容,控制器就认为「有一套程序在这儿跑着」,Init 时的新旧对不上就会失败。

第三处是本地与远端在 Multiuser Explorer 里的关联状态,也就是界面上显示的那对 Local / Remote。

# 开发 PC 侧:进入 PLC 项目根目录,先看有没有残留(-Force 才会显示隐藏项) Get-ChildItem -Force -Name | Where-Object { $_ -match '^\.git' } # 确认是旧项目的残留后再删,删之前把整个项目文件夹复制一份备份 Remove-Item .git -Recurse -Force

-Force的作用是把隐藏项也列出来,不加这个参数你会以为目录很干净。删除 .git 等于放弃这个项目此前所有的本地提交记录,所以命令敲下去之前先备份,这是血泪经验,不是客套话。

控制器侧清 Boot 要在停机窗口做:

# 控制器侧:清空 Boot 目录后重启 TwinCAT 运行时,PLC 会停止运行 Remove-Item -Path "C:\TwinCAT\3.1\Boot\*" -Recurse -Force

注意这条命令执行完控制器上的程序就没了,必须重启运行时再重新激活。很多人在这一步犹豫,结果只清了本地没清控制器,Init 依旧失败,白折腾一轮。

至于控制器上那个仓库根目录(默认在 ProgramData 下厂商命名的那一层里的 MultiuserRepository),里面的历史仓库不用清。它们是按名字分文件夹存放的,留着不影响新项目,将来要找回旧版本还用得上。

2.3 版本与硬件不匹配:为什么第三方 PC 上总是「这样那样的问题」

官方手册对硬件的要求写得比较宽松,但实测结论要严苛得多:这套功能在厂商自家的 IPC/EPC 上稳,换到第三方 PC 上就各种莫名其妙——Init 时好时坏、History 刷不出来、Get This Version 之后文件没变。根因不在 Git,而在 ADS 通道和运行时版本的一致性问题。

版本这一块,实测的有效组合大致是:

| 环节 | 最低要求 | 实测建议 | | 控制器操作系统 | Windows 7 / 10 | 与 TwinCAT 运行时版本匹配的官方支持系统 | | 控制器侧运行时 XAR | 3.1.4024.15 | Build 号越高越好,避免早期 4024 的已知问题 | | 开发环境 XAE | 3.1.4024.15 | 与控制器 Build 号尽量保持一致 | | 控制器硬件 | 厂商自家 IPC / EPC | 第三方 PC 上失败率高,不建议用于正式项目 |

XAE 比 XAR 高一个小版本通常还能忍,反过来低太多就麻烦了:新版本控制器生成的仓库结构,旧版开发环境读不懂,表现就是 History 列表能刷出来但双击没反应,或者比较窗口一片空白。

所以当你在第三方机器上反复失败时,先别怀疑操作步骤,把两边版本号拉出来对一遍,再换一台厂商自家的控制器试一次。如果换了就正常,那问题定性为环境不匹配,不用再往下查了。

2.4 现有项目接入:先初始化,再做激活下载

这条顺序错误引发的故障特别隐蔽。正确的顺序是:新建或打开 PLC 项目 → 在项目属性里启用 Multiuser → 打开 Multiuser Explorer,选路由、填仓库名、点 Init → 之后才去激活配置、下载到控制器。

反过来的顺序会怎样?先激活下载,控制器上已经有程序在跑了,此时再点 Init,远端仓库会被当前运行的程序「预置」一份内容,本地这边却还是空的,两边的初始版本对不上,History 里第一条提交记录的差异会莫名其妙多出一堆文件。

如果确实已经下载过了才发现要接入版本管理,也不用推倒重来,但要在 Init 之前把控制器 Boot 清空并重启,让控制器回到「没有程序」的干净状态,再按上面的顺序走一遍。对于现有的 PLC 项目,如果知道控制器上已有的仓库名,可以直接从 Multiuser Repository 的下拉菜单里选,不必新建。

3. 提交、比对、回退三连坑:Login 弹窗背后的版本逻辑

过了 Init 这一关,下一步就是日常操作。这套机制最反直觉的一点是:版本提交的触发点不是你主动点「提交」,而是每次向控制器 Login。理解了这个设计,很多「报错」就不算报错了。

3.1 每次 Login 都弹 Update Message:提交信息就是版本号

配置启用 Multiuser 之后,每次在 TwinCAT 里对控制器执行 Login,都会弹出一个要求填写 Update Message 的窗口。新手第一反应是「这弹窗能不能关掉」,答案是不能,而且它很重要——你填进去的这行字,就是 History 列表里那条记录的标题。

所以别填「123」「test」「update」这种,隔两周自己都认不出来。可行的写法是把版本号和改动内容绑在一起,例如「V1.0 First Code」「V1.0.1 Change Data」,改了什么一眼可辨。这个习惯在单人开发时看不出价值,一旦两个人交替往同一台控制器提交,History 就是唯一的脉络来源。

这里有个容易误解的点:Login 时提交的是「当前工程与控制器上运行版本的差异」,不是你手动选中的某些文件。也就是说,你在编辑器里改了但没保存的文件,不会被提交进去;你没改但 TwinCAT 自动生成的中间文件,反而可能被带进去。所以提交前先 Ctrl+S 全保存,是最省事的做法。

3.2 版本比较打不开:两处设置少一处都不行

点开 History,选中记录右键 Compare,结果窗口是空的,或者弹出来的不是熟悉的 TwinCAT 项目比较界面——这个故障十有八九是环境设置没做全。它需要两个独立的开关:

第一个开关在「工具 → 选项 → 源代码管理(Source Code Control)」里,把插件选成 Git。不选这一项,TwinCAT 不知道用哪个工具去取仓库里的源代码,比较动作自然无从发起。

第二个开关在 TwinCAT Project Compare 工具内部。从 TC3 图标进 Tool,打开 TwinCAT Project Compare,在主菜单「Tool → Configure User Tools」里点 Export Configuration,选择 Git 插件,启用默认的全局 Git 配置。这一步的作用是把 Git 的取数能力注册给比较工具,缺了它,比较窗口能打开但没有数据。

两处都配好之后,比较界面会把差异分成三类显示:新增、删除、逻辑修改,不同处标红。双击某个红色的 POU,可以展开到具体代码行。想拿历史版本的某一段覆盖当前版本,就在差异图上点感叹号上方的 Accept Single、Accept Block 或 Accept All——分别对应接受单处、接受整块、全部接受,颗粒度自己挑。

3.3 Get this version 之后那个 Reload 提示:代码其实已经改了

在比较界面右键选 Get this version,开发 PC 上的当前 PLC 项目会回退到该版本。紧接着 TwinCAT 弹出一句「File has been changed outside the environment. Reload the new file?」,很多人被这句话吓到,以为操作失败了,其实这是正常的提示。

它的意思是:比较工具在后台直接改了项目里的 POU 文件,改完之后告诉编辑器「文件变了,要不要重新加载显示」。这里的关键是——无论你点「是」还是「否」,磁盘上的代码都已经变成旧版本了,Reload 只是决定编辑器的显示跟不跟。点「否」的话,编辑器窗口里还是旧内容,但你如果直接编译,编出来的会是新(旧版本)的代码,这种不一致最容易把人带沟里。

我的做法是永远点「是」,让显示和磁盘对齐。点完之后别急着编译下载,先在比较界面确认一遍差异项,确认这次回退的确实是想要的那一版。

3.4 恢复错了还能再捞回来

回退到历史版本之后发现选错了,很多人第一反应是「完了,改动没了」。其实不会——回退只是在当前工作区里把文件内容换成旧版,仓库里的提交记录一条都没少。History 列表刷新一下,刚才那个较新的版本仍然在里面,右键再 Get this version 就能回去。

真正会丢东西的场景是反过来的:你在回退后的旧版本上继续改、继续 Login 提交,那么新提交是建立在旧版本之上的,原来那条较新版本的分支关系就断了,History 变成一条线性往前的链,中间那段需要靠版本比较手动挑回来。所以正确的节奏是「回退 → 确认 → 再改 → 再提交」,中间别省确认这一步。

想从旧版本里只取一小段而不是整体回退,就用 3.2 里说的 Accept Single / Accept Block,避免整体覆盖带来的副作用。

4. 两台 PC 交替提交:Local、Remote 不一致时的处理顺序

单人开发基本碰不到冲突,一旦有第二台 PC 接进来,Local 和 Remote 的关系就成了主要矛盾来源。这一章按「第二台 PC 首次接入 → 发现落后 → 处理冲突 → 精确装载」的顺序走。

4.1 第二台 PC 怎么接上控制器上的仓库

第二台 PC 要做三件事:装同版本 TwinCAT、添加控制器路由、把仓库同步下来。前两步和第一台 PC 没区别,第三步有个容易漏的动作——必须知道控制器上仓库的名称。

拿到名称的途径有两条:问第一台 PC 的操作者,或者从 Multiuser Explorer 里选控制器后,从 Multiuser Repository 的下拉菜单里选目标仓库(已存在的仓库会列出来)。选好之后点 Init Local and Remote,系统会提示 Remote 中已经存在数据仓库,问要不要读取,这里必须回「是」。

回「是」之后,控制器上的整个仓库历史会被同步到第二台笔记本上,包括第一台 PC 提交的那两个版本。这一步如果点了「否」,本地就会建一个空仓库,两边的历史从此对不上。

还有个前置条件:第二台 PC 上得有对应的 PLC 项目。能直接从第一台 PC 拷项目文件夹是最省事的,拷不了就从控制器上传源程序。上传的目的主要是拿到工程结构,源代码能不能读到不一定——如果第一台 PC 下载时没勾选下载源代码,控制器上是没有源码的,这时候只能靠拷项目文件。

4.2 LocalsBehindRemote:本地落后时别急着改代码

第二台 PC 提交完「V2.0 Change Para」和「V2.0.1 Second Code」两个版本后,回到第一台 PC,打开 History 会看到两条红色记录——那是 Remote 新增的、本地没有的版本。同时 Status 界面会给出一行提示:LocalsBehindRemote。

这个提示的含义很直白:本地程序版本比控制器上的旧,控制器那边有你没有的修改。此时如果直接在本机改代码再 Login,等于在旧基础上叠加新改动,一旦提交,Remote 上的两次修改就被绕过去了,后续合并会非常麻烦。

正确的处理是打开 Confict 界面,它会明确列出「本地丢失了远程的若干次修改」。看完再决定:要么点 Get Latest 把远程最新拉下来,要么从 History 里精确挑一个版本装载(见 4.4)。无论走哪条,动手改代码之前先把本地补齐,这个顺序不能反。

4.3 Get Latest 之后提示「程序从外部改动」怎么理解

点 Get Latest,TwinCAT 会弹提示说程序从外部被改动了,并列出与当前代码的区别,让你选 Accept 或拒绝,也可以直接关掉。这和 3.3 里的 Reload 是同一类提示,都是「文件被工作区之外的东西改了」的意思,只不过这次的改动方是远端仓库。

Accept 就是接受远端版本覆盖本地,拒绝就是保持本地不动、稍后手动处理。这里有个判断依据:如果你本地没有未提交的修改,放心 Accept;如果本地已经改了一半,先别 Accept,把本地改动记下来(截图或者复制到临时文件),再接受,然后把改动手工合回去。

关掉提示不理会也是允许的,但此时本地和远端仍然是不一致的,Status 还会继续报 LocalsBehindRemote,下次打开照样要处理,只是推迟了。我不建议拖,因为拖到后面改动越多,手工合的成本越高。

4.4 精确装载某个 Remote 版本:V2.0.1 的完整路径

如果不想直接拉最新,而是想装载某个特定版本(比如第二台 PC 提交的 V2.0.1),路径是:History 里选中 V2.0.1 → 右键 Get This Version → 系统提示代码从外部改变、是否装载 → 选「是」。

装载完成后打开 PLC 代码,能看到第二台 PC 加的那个变量和那段逻辑,说明同步成功。此时再刷新 History,会看到本地也跟上了这个版本,红绿标记消失。

这套操作的价值在于它给了你「选择性前进」的能力:不是被迫接受最新的全部改动,而是可以从历史里挑一个已知可用的版本落地。在调试现场,这个能力比标准的 Git checkout 更顺手,因为整个动作都在 TwinCAT 界面里完成,不用切到命令行。

5. 排查清单:五个让 AdsGitServer 直接失效的坑

下面这几条都是我在实际调试里撞过的,按「现象 → 原因 → 解决」写,遇到对得上的直接照做。

5.1 现象:同一个项目文件夹,Git 命令和 Multiuser 互相打架

原因:TwinCAT PLC 项目的文件夹一旦启用了 Multiuser,就已经被 AdsGitServer 接管了。此时再在这个文件夹里手工执行 git init,会创建第二套 .git 结构,两套版本控制指向同一个工作区,提交时互相覆盖,History 里的记录会莫名其妙消失或者重复。

解决:一个文件夹只能归一套 Git 管。要留 Multiuser,就别在这个目录里敲 git init;要用标准 Git 管,就先把 Multiuser 关掉、把 .git 清干净再初始化。判断当前归谁管,看项目根目录下 .git 的 config 里 remote 指向的是不是 ADS 那条通道就知道了。

5.2 现象:Word、PDF 这些文档提交上去了,但没法比较和回退

原因:AdsGitServer 的比较能力来自 TwinCAT Project Compare,它只认 PLC 的 POU、GVL 这类结构化对象。非代码类文件在 Git 层面可以提交、可以留历史,但比较工具打不开,也就谈不上按差异合并或者从界面回退。

解决:这类文件走标准 Git 那条路。在文档目录里用命令行操作:

# 查看本地提交历史,--oneline 每个提交压一行,--decorate 显示分支和标签 git log --oneline --decorate # 回退到上一个版本,--hard 会把工作区文件一起还原 git reset --hard HEAD^

HEAD^指当前提交的上一级,回退两级写HEAD~2。--hard是不可撤销的,执行前先确认没有未提交的改动,或者先git stash存一下。回退完打开文档,内容确实回到了上一版,这就是它相对图形界面的优势——文档类文件的版本恢复只能靠命令行。

注意即便是标准 Git,对二进制文档也只能做到整文件回退,做不到逐段比较,这是文件格式决定的,不是工具的问题。

5.3 现象:仓库能被别人读到,甚至被改

原因:Multiuser 走的是 ADS 通道,仓库访问权限完全继承 ADS 的安全配置。测试环境里为了省事通常用无加密方式,一旦这套配置被带到实际项目,任何能连上控制器的人都能提交和回退。

解决:正式项目里把 ADS 的安全方式配起来——用户名密码、预共享密钥或者证书,按现场条件选一种。多人协同的时候尤其要配,否则谁改的、什么时候改的都说不清,出了问题只能靠猜。

5.4 现象:两个人同时改不同的 POU,History 变成一团乱麻

原因:这套机制本质上是线性提交,A 提交完 B 提交,B 的提交是建立在 A 之上的。如果两人各自在本地改了同一段逻辑再先后提交,后提交的那次会把先提交的覆盖掉,而且不会有任何「冲突」提示。

解决:多人开发前把约定写死——谁负责哪几个 POU、什么时候可以 Login、提交信息怎么填。真到了要并行改同一段代码的程度,这套线性机制就不合适了,老老实实人工合并比事后追查省事。

5.5 现象:换了新 PLC 项目,旧仓库的历史还在但用不上

原因:控制器上的仓库目录是按名字分文件夹存的,旧仓库不会自动清理,新项目如果沿用了旧仓库名,就会看到一堆与当前项目无关的历史记录,容易误装载。

解决:新项目用新的仓库名,别复用。旧仓库留在那里不影响运行,需要找旧版本时再按名字选回来。反过来,如果确实想在新项目里继承旧历史,那就别清 Boot、别新建仓库,直接从下拉菜单选旧仓库名接入。

6. 快速定位:三步把问题压到最小范围

现场没有那么多时间逐个试,我习惯用一套固定动作把问题范围压小:先确认服务层,再确认通道层,最后确认仓库层。三层里任意一层不通,后面的操作全都是白费。

服务层的判断只需要一条命令:查 TwinCAT 3 System Service 和 TwinCAT3 AdsGitServer 是否都是 Running。前者挂了连 PLC 都登不上,后者挂了能登录但所有 Git 操作失败,这两种表现差别很大,先分清能省一半时间。

通道层看 ADS 路由。控制器的 IP 改过没有、路由表里的设备还对不对、是不是加到了另一台设备上,这些都能在路由配置界面几秒钟看出来。通道不通的典型表现是 Init 时长时间无响应,而不是立刻报错。

仓库层看三处残留:本地项目里的 .git、控制器 Boot 目录里的内容、界面上 Local 与 Remote 的关联状态。三处只要有一处是旧的,Init 就会失败。

把常见现象和第一步动作对成一张表,遇到问题先查表,查完再动手:

| 现象 | 优先怀疑 | 第一步动作 | | Multiuser Repository URL 空白 | 输入框变更事件未触发 | 删掉仓库名末位字符再补回 | | Init local and Remote 点了没反应 | 服务未运行或路由不通 | 查两个服务的状态与路由表 | | Init 提示仓库已存在 / 直接失败 | Local、Remote、Boot 有残留 | 清 Boot 重启运行时,删本地 .git | | 版本比较窗口空白 | 两处 Git 插件设置没配全 | 查源代码管理设置与比较工具配置 | | Login 后 History 没有新记录 | 提交时未保存文件 | 全保存后重新 Login | | Status 显示 LocalsBehindRemote | 本地落后远端 | 先 Get Latest 或 Get This Version | | Get This Version 后提示文件被外部修改 | 比较工具已直接改写文件 | 选「是」重新装载,再核对差异 |

这套动作我从踩坑里攒出来的:早期遇到 Init 失败,第一反应总是重装软件,一装半小时,装完照样失败,因为根因在控制器 Boot 里那堆旧文件上。从那以后我每次接新项目,都强制按「查服务 → 对版本 → 清残留 → 再 Init」走一遍,哪怕看起来一切正常也走,多花三分钟,省掉的是半小时的瞎猜。这份文档里把每一步的现象、原因和操作顺序都串起来了,遇到对不上的现场,翻到对应章节照着做就行,希望帮到你。

本文还有配套的精品资源,点击获取