ET9 项目包更新实战:基于 Git master/dev 分支的包同步与合入方案
【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET
ET9 将框架拆分成了一个个标准 Unity Package(以cn.etetet.前缀命名的 npm 包),但这对使用方而言影响不大——包更新并不需要逐包手动拷贝替换,而是通过一套基于 Git 分支的固定流程完成:项目与包全部入库作为 master 分支,开发在 dev 分支进行,每次更新时先更新 master 再合并回 dev。本文以 8.3ET9项目怎么进行包更新.md 为核心,结合仓库中Packages/目录、manifest.json与初始化脚本,完整讲解这套包更新工作流,并给出可直接复制的 Git 命令序列与常见问题排查方法。读完本文,你将掌握 ET9 项目"先同步上游包、再合入开发分支"的标准更新姿势,避免把包代码和个人业务代码混在一起造成更新冲突。
一、背景:ET9 为什么变成了"包"的形式
ET9 与以往"一个巨型仓库"的形态最大的区别在于框架本身被拆分成大量独立包,存放在Packages/目录下。以当前仓库为例,可以看到cn.etetet.core、cn.etetet.loader、cn.etetet.login、cn.etetet.actorlocation、cn.etetet.statesync等几十个包,每个包都是标准 Unity Package,命名格式统一为cn.etetet.+包名(规范详见 8.1ET Package制作指南.md)。
从机制上看,这些包本质上是 npm 包,托管在 GitHub Packages 上。Unity 通过manifest.json中的scopedRegistries来拉取它们:
{ "scopedRegistries": [ { "name": "ET-Packages", "url": "https://npm.pkg.github.com/@ET-Packages", "scopes": [ "cn.etetet" ] } ] }这段配置的语义是:所有cn.etetet作用域下的包都从@ET-Packages这个私有 registry 解析。包安装完成后会自动位于Packages目录下(每个包内部还带有package.json、packagegit.json、Ignore.ET.*.asmdef等元数据文件,例如 cn.etetet.core/package.json 中声明了该包对cn.etetet.sourcegenerator、cn.etetet.memorypack的依赖)。
虽然底层机制是 npm 式包管理,但如原文档所说,"对用户来说,区别不大"——你不需要像手动拷 DLL 那样管理包的物理文件,需要做的只是把"项目 + 包"整体纳入自己的 Git 仓库,然后按分支流程同步更新即可。
二、核心思想:master 同步上游,dev 承载开发
ET9 包更新方案的核心是一个"双分支模型":
- master 分支:存放"项目 + 全部包"的完整快照,是纯上游内容。它用于接收来自 ET 官方的包更新,保持与上游一致。
- dev 分支:从 master 切出的开发分支,承载你自己的业务代码、自定义配置和本地改动。
为什么要这样做?因为包更新是高频、且来自上游的事件,而开发改动是持续累积的本地产物。如果不做分支隔离,git pull上游包更新时会直接污染正在开发中的代码,冲突难以收拾。把两者放在不同分支上,每次更新就退化成两个稳定操作:
- 在 master 上拉取/覆盖包更新,提交;
- 在 dev 上合并 master,把更新合入开发线。
从仓库结构看,这套模型与 ET 官方仓库自身的组织方式一致:框架代码、Packages/、Book/文档与Scripts/工具脚本共存于仓库根目录,说明"包与项目同仓"是官方认可的使用形态。初始化脚本 Initialize-Project.ps1 也印证了这一点——它只负责初始化主包、链接ET.sln、编译 Luban 与 CodeMode 工具,并不会替你管理 Git 分支,分支策略需要开发者自己落实。
三、初始化:把"项目 + 包"提交为 master 分支
在开始这套更新流程之前,先要完成一次性的仓库初始化。参考运行指南(1.1运行指南.md),拿到 ET9 项目后:
在项目根目录执行初始化:
pwsh ./Scripts/Initialize-Project.ps1脚本会检查环境(需要 .NET SDK 10+、Git)、生成
MainPackage.txt、把主包的ET.sln链接到项目根目录,并编译 Luban 与ET.CodeMode等工具。初始化完成后,将整个项目目录(含
Packages/)初始化成本地 Git 仓库,提交为 master 分支并推送到自己的远端仓库:git init git checkout -b master git add . git commit -m "init: ET9 project with packages" git remote add origin <你的仓库地址> git push -u origin master从 master 切出开发分支 dev,后续所有日常开发都在 dev 上进行:
git checkout -b dev git push -u origin dev
这里的关键点与原文档完全一致:master 分支上保存的是"项目 + 全部包"的整体,而不是只提交业务代码。这样每次上游包更新时,master 分支就是一个干净的、可整体拉取的基线。
四、日常包更新:完整的 Git 命令流程
原文档给出的更新流程可以概括为四个步骤:切 master → 更新并提交 → 切回 dev → 合并 master。展开成可执行的命令序列如下。
步骤 1:切到 master 分支并拉取上游包更新
git checkout master包更新的来源有两种情况:
- 如果你的仓库直接 fork 或 clone 自 ET 官方仓库,则直接拉取上游:
git pull origin master - 如果包的更新是通过 Unity Package Manager 解析(例如官方发布了新版本包),需要先在 Unity 中刷新解析到的包版本(重新打开工程或点击 UPM 刷新),包文件更新到
Packages/目录后再走 Git 提交流程。
无论哪种方式,最终都要保证 master 分支上的Packages/目录内容是"最新上游包"的状态。
步骤 2:在 master 上提交包更新
git add -A git commit -m "update: sync upstream packages" git push origin master这一提交只应包含包的变更。建议每次更新单独提交,保留清晰的更新历史,方便日后回溯"某次包更新引入了什么问题"。
步骤 3:切回 dev 分支
git checkout dev步骤 4:把 master 合并进 dev
git merge master git push origin dev合并完成后,本次包更新就完整进入了开发分支。原文档强调"这样就完成了合并",其本质就是利用 Git 的三方合并能力,把上游包变更与本地开发改动按文件粒度自动合并。
五、进阶:冲突处理与合并策略
dev 分支上如果改过Packages/下的包文件(比如修过框架 bug、改过包内配置),合并 master 时就会产生冲突。处理原则:
- 优先保留上游:包的源码应以上游为准,本地对包内文件的修改尽量通过"包外扩展"或"二次封装"实现,而不是直接改包。ET 包规范(见 8.1ET Package制作指南.md)也建议通过
packagegit.json声明依赖、在包外编写代码,从结构上减少直接改动包的需求。 - 冲突时逐文件裁决:
git merge master报冲突后,用git status查看冲突文件,逐文件确认是保留上游、保留本地还是手动合并。 - 合并不了及时中止:如果本次更新问题较多,可以
git merge --abort退回合并前状态,排查清楚后再重试。 - 可选策略:如果团队希望 dev 的历史更整洁,可以改用
git rebase master将 dev 变基到最新 master 上;但注意 rebase 会改写提交历史,多人协作时需谨慎,默认推荐 merge。
六、配套细节:包结构、主包与依赖说明
理解了分支流程后,补充几个与"包更新"密切相关的仓库细节,帮助你在更新时判断哪些文件属于包、哪些属于项目自身:
- 包目录规范:
Packages/下的cn.etetet.*目录即为一个个 ET 包。每个包包含Scripts/(热更代码)、Runtime/(AOT 代码)、DotNet~(服务端专用工程,~号防止被 Unity 编辑器识别)、Luban/、Proto/等目录,以及package.json、packagegit.json和顶层Ignore.*.asmdef(默认让包代码不生效,运行ET->Init后才会装配,详见 8.1ET Package制作指南.md)。 - 包的 Id 与依赖:
packagegit.json中定义了包的 Id、名字与 Git 依赖(例如 cn.etetet.core/packagegit.json 中"Id": 1, "Level": 1,AllowAnyPackageAccess为 true)。包 Id 由官方统一分配,更新时留意 Id 是否变化有助于判断包的版本归属。 - 哪些包会一起更新:官方包目录见 8.2ET Package目录.md,从
cn.etetet.core(纤程、网络、Entity 基础)到cn.etetet.statesync(状态同步 demo)、cn.etetet.lockstep(预测回滚帧同步)等,更新时可根据自己项目实际引用的包判断影响范围。值得注意的是,当前仓库的manifest.json只声明了cn.etetet.mapplay一个file:本地包依赖,其余大量包是随仓库整体携带的——这正说明"包与项目同仓、整体入库、分支同步"是 ET9 的标准使用方式。 - 热更相关目录:若项目启用了 HybridCLR 热更新,打包链路(
HybridCLR -> Generate、ET -> HybridCLR -> CopyAotDlls)等操作在更新包后可能需要重做,更新后建议按 1.1运行指南.md 的打包过程重新走一遍。
七、总结与最佳实践清单
ET9 的包更新本质上是一套"上游同步 + 本地合入"的 Git 分支工作流,官方文档以极简的方式给出了核心步骤。落到实操上,可以整理为以下最佳实践清单:
- 一次性初始化:把"项目 + 全部包"整体提交为 master 分支并推送远端,日常开发一律在 dev 分支进行。
- 每次更新都走完整流程:
git checkout master→ 拉取/刷新包更新 →git add -A && git commit && git push→git checkout dev→git merge master→git push。不要跳过任何一步,尤其是"先提交 master 再合并 dev"的顺序不能颠倒。 - 尽量不改包内源码:对包的定制通过包外代码、二次封装或依赖声明实现,从源头减少合并冲突。
- 更新后验证:包更新合入 dev 后,建议重新执行
pwsh ./Scripts/Initialize-Project.ps1中涉及的工具编译步骤,并在 Unity 中跑通ET->Init与 Play 验证,确认包版本变更未破坏现有功能。 - 保持 master 干净:master 上只应有来自上游的包更新提交,不要混入业务代码,否则会失去分支隔离的意义。
这套方案不依赖任何第三方工具,只使用 Git 原生能力,非常适合个人开发者或中小团队在 ET9 上长期跟进官方包更新。
【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考