大型资产版本控制
全库目录221
本文目录20
二进制源文件每次修改形成独立逻辑版本,底层存储是否差分取决于系统,两人同时编辑时字节合并并不理解创作内容。大型资产版本控制需要同时安排历史、带宽、锁和文件粒度,构建验证再确认一个提交确实能生成结果。
文本与二进制的差异
代码、JSON、YAML 等文本可以按行比较差异并合并。.psd、.blend、.mb、贴图、音频等二进制通常只能整体替换。
两人同时编辑同一二进制时,最后必须选一个版本或人工在 DCC 重做合并。工具无法凭字节差异理解“保留 A 的角色、B 的灯光”。
因此先确定哪些人需要同时编辑什么内容。两人分别修改角色网格和灯光时,可以把二者放在独立文件,再由场景引用;必须共同修改同一个二进制源时,则以独占锁串行交接。锁降低同时写入的概率,文件拆分增加可以并行的单元,短任务分支减少这些单元长期偏离主干的时间。三者处理不同的冲突来源。
历史与存储服务
Git 的对象历史
普通 Git 克隆会获得分支可达历史对象。大二进制内容改变时产生新的Blob对象,即使删除当前文件,历史仍持续占空间。
Git 擅长分支与文本合并,但大型资产库会遇到克隆、拉取、检出和仓库维护成本。ZIP 封装不能保证有效差分:压缩数据的局部修改可能改变大段字节,Git 的对象差分压缩也不等于可理解的资产内容对照。审查仍需网格、图像或元数据的专用产物。
Git LFS
Git LFS 用小型指针文件替代 Git 中的大文件内容,真实对象存储在 LFS 服务。.gitattributes 决定哪些模式经过 LFS Filter。
暂存时过滤器把工作区文件转换为指针,并把真实字节写入本地LFS对象缓存。指针记录协议版本、对象SHA-256和字节长度;检出时过滤器按该身份取得真实内容。工作区看见大文件,提交对象看见小指针,两者由哈希连接。
真实内容转移到LFS以后,Git提交只负责引用对象,LFS服务负责提供字节。二进制仍需要锁或人工合并;容量、带宽和下载权限仍由对象服务承担。CI也必须显式取得对象,指针文件存在不等于资产到位。海量小文件的目录扫描与检出开销则仍留在客户端,不能只用总字节数估算工作区成本。
.gitattributes 应在大文件首次提交前配置并进入版本控制。把历史迁移到 LFS 会改变提交ID,由团队统一安排迁移与客户端切换。
跟踪、对象上传与干净检出
以已安装Git与Git LFS的项目为例,先执行git lfs install --local配置当前仓库的过滤器,再执行git lfs track "*.psd" --lockable,把生成的.gitattributes与PSD源文件一起暂存。git lfs status检查本次哪些资产经过LFS;提交后的Git对象应是带OID和长度的指针,本地工作区仍保留真实源文件。仅在本机安装LFS却未提交跟踪规则,其他机器就无法沿同一契约处理文件。
发布时LFS对象与Git提交共同可用。正常推送由LFS钩子上传对象,必要时用git lfs push origin HEAD显式完成当前引用所需对象,再推送Git引用;上传失败时保留失败结果并阻止进入构建队列。干净工作区取得指定提交后执行git lfs pull,再运行git lfs fsck并核对资产清单;跳过下载时即使指针路径存在,DCC拿到的仍可能只是指针文本。已有普通Git历史的迁移另在镜像库按批准计划进行,首次跟踪规则只影响按规则重新加入的内容。
Git LFS Lock
对不可合并格式可启用 Lockable。用户编辑前锁文件,成功提交并确认对象可用后解锁。例如已受跟踪的Assets/Hero.psd先执行git lfs lock Assets/Hero.psd,检查服务返回的锁持有人后再编辑;锁请求失败就保留只读,避免把本地可写误当成服务器已经授予编辑权。工具可在 DCC 打开/保存时显示锁负责人。
锁是协作协议,不是完整权限系统。离线编辑、绕过客户端或强制解锁仍可能产生冲突。团队要定义:谁能强制解锁、请假/离职锁如何处理、锁多久提醒。
Perforce Helix Core
Perforce 是集中式版本控制,常用于大型游戏资产。基本概念:
- Depot 保存版本;
- Workspace 映射本地文件;
- Changelist 组织一次提交;
- 文件类型可设置二进制、文本、独占锁;
- Stream 组织主线与分支;
- Shelve 用于共享未提交改动和审查。
一次编辑可以按如下顺序落地:在正确的工作区视图中同步目标版本,用p4 change建立编号变更集,将要修改的文件以p4 edit -c <编号> <文件>加入其中。文件类型的独占打开设置由管理员维护;取锁失败时保留工作副本并处理交接。DCC保存以后检查变更集中的新增、修改、删除与引用,使用p4 shelve -c <编号>保存可供审查的未提交版本,最后以p4 submit -c <编号>提交。
搁置保留的是待审查内容,正式版本仍由成功提交形成。工作期间仓库有新版本时,先同步并处理待解决文件,再重新验证候选变更;二进制冲突需要选择其中一份或在DCC合成结果,不能把“已解决”按钮当成语义合并。提交结果不明时查询该编号是待提交还是已提交,再决定重试,避免重新建立一份难以对账的变更集。P4提交语义和冲突解决分别定义这两步。
成员可只同步工作区视图内的目录。视图仍需覆盖本次资产的依赖闭包:只取得角色网格却漏掉其材质和骨骼,下载成功也不能构成完整输入。
代价是服务器运维、网络依赖、工作区与分支流规则和管理员治理。错误的视图或大规模自动文件对账 也会制造大量无关变更。
PlasticSCM / Unity Version Control
PlasticSCM(Unity Version Control)提供 Changeset、Branch、合并、Lock 和面向非程序用户的 Gluon 工作流。Gluon 允许用户选择性下载和提交,不要求理解完整分支模型。
Gluon的编辑流程先更新工作区,取得所选文件的最新版本,再检出需要编辑的文件并确认锁。DCC保存以后,客户端显示已修改状态;在提交面板同时选择源、元数据与依赖变化,检查内容并提交,取得新的变更集ID。工作区保存只改变本地文件,成功提交才使其他成员可取到该版本。提交界面还允许提交后保留锁,适合继续编辑;保留锁并不阻止其他成员读取已提交版本。
选择性工作区可能由不同时间更新的文件组成,因此任务要额外记录实际输入修订。美术可以只下载当前任务的依赖,构建服务则按已提交的完整版本重建依赖闭包;直接复制美术工作区会把未更新的材质带入构建。分支切换、锁规则和服务账号权限也要在同一条编辑—提交—干净构建路线中检查,费用和部署能力按采用时的服务约定选择。
选择方案
选型先使用同一份项目样本,固定以下输入:
- 资产总量、日增量和单文件大小;
- 文本/二进制比例;
- 分支与发布数量;
- 地域、网络和远程办公;
- 锁的频率与粒度;
- 权限与外包隔离;
- CI与构建集群并发;
- 备份、灾备、审计和成本。
分别测首次取得完整依赖、单日增量同步、切换发布版本、上传新二进制和多人争用锁的耗时。再模拟对象服务缺失、客户端断连和备份恢复。首次下载近似受所需字节/有效带宽约束,小文件较多时还要叠加请求与文件创建成本;锁占用时间则决定同资产的排队等待。将这些测量与每日编辑量、并发构建数对应,才能知道瓶颈属于带宽、存储还是协作粒度。
检出契约
一次编辑同时涉及基线版本、编辑权和工作区字节。下面的工具中立流程把三者依次核对;稳定路径与依赖来自项目资产数据库,锁和写权限由实际服务检查。
verify current revision and lock owner
sync required source and LFS objects
edit under agreed ownership
submit source, metadata and dependency changes together
verify submitted revision from an independent workspace
release the editing lock according to the service policy检出验证可以用内容哈希连接两层存储。Git 中的指针声明 LFS 对象的 SHA-256 和字节数,工作区取得真实文件后计算同样的值,两者一致才说明这次输入到位。版本库提交成功但 LFS 上传失败时,其他机器仍可能拿不到对象;提交和对象可用性应共同进入构建检查。恢复演练既恢复 Git 元数据,也恢复 LFS 对象与访问配置。
一次可复现检出可以追踪三份身份:提交C引用指针P,P声明对象哈希H与长度N,服务返回文件F。构建先核对F长度为N、SHA-256为H,再把C、工具版本与依赖清单写入构建记录。只恢复C而没有H对应对象,检出得到指针文本或下载错误,仍不是可构建备份。恢复演练因此从独立工作区使用备份服务取回F,并实际跑导入验证。
某些服务在提交成功时自动释放编辑锁,干净检出的验证便由合入或发布门禁继续承担;它不要求已经自动释放的锁重新存在。
锁与提交还存在时间边界:A在基线C取得锁并开始编辑,B绕过锁提交了新基线D;A提交前仍须同步并核对服务端版本。锁证明约定的编辑权,不证明本地基线新鲜。发现D后先保存A的工作副本,再由资产负责人选择或在DCC合并,确认引用整体有效后形成新提交;自动覆盖会丢失其中一方内容。
协作与恢复
文件粒度
版本控制无法弥补不合理的资产结构。一个 20 GB 单体关卡会让锁和提交都难以并行。
可拆分:
- World Partition/关卡实例/Sublevel;
- Prefab/Blueprint/场景对象;
- USD 层/Reference;
- 材质、模型、动画与贴图独立资产;
- 配置与生成缓存分离。
拆得过细又会增加引用、加载和文件数量。边界对应资产负责人、并行编辑和运行时职责。
派生文件
派生数据按重建能力分三类:
- 可快速确定重建:忽略并缓存;
- 重建昂贵但确定:共享构建缓存/产物;
- 不可稳定重建或需要审查:作为正式资产版本化。
构建缓存键包含源内容、依赖内容、工具版本和配置的哈希;同名文件不能作为缓存身份。工具升级后使用旧缓存会使新提交悄悄携带旧导入结果。忽略规则、LFS模式和输出目录由管线维护,临时文件、自动保存与本机导入缓存留在各自缓存位置。正式发布清单引用不可变产物,缓存淘汰时保留可重建源及发布所需的长期产物。
分支、主干与合入队列
二进制资产不适合长期分支。两个分支分别修改同一场景或源文件,数周后几乎无法自动合并。资产团队通常更适合短生命周期任务分支、频繁同步主干和明确锁定。
一次 Changelist/Changeset 应表达一个可审查工作单元。模型、贴图、材质和引用调整若共同构成同一交付,应一起提交,避免主干出现“模型已换但材质还没来”的中间状态。
合入队列把候选变更与一个确定的主干版本绑定。设当前主干为C,候选A合到C后得到T,验证记录保存T的版本ID、源清单与工具配置哈希。通过后只有主干仍为C,队列才把入口推进到T;主干已变为D,就重新把A合到D、得到新候选并重跑受影响验证。服务可用串行合入权限或期望旧引用的条件更新维护这一步,不能在验证后无条件推送。
例如A改骨骼结构,B改依赖旧骨骼的动画,两者分别在C上通过。A先合入后,B必须针对A所在的新基线构建,才能发现绑定失配。人工审查同样绑定候选内容;重新合并改变了二进制或依赖时,相关审查产物也要重新生成。源、元数据和引用调整作为同一可审查交付单元提交,再由队列确认它与当前主干相容。
发布分支按发布策略接收修复。修复记录其挑选提交或集成来源,避免同一二进制在主干和发布分支被独立修改后无法判断哪个是权威版本。
二进制资产审查
代码审查页面看不到 .fbx 或 .uasset 的有意义差异。管线可以自动生成审查产物:
- 前后转台渲染、截图或视频;
- 包围范围、顶点、材质、骨骼、纹理和内存差异;
- 引用增加/删除与资源包影响;
- 验证器结果和预算变化;
- DCC 源数据、导入器设置 和工具版本;
- 场景/Prefab 的结构化语义差异。
Perforce Shelve、Git PR 产物或 Plastic Changeset 预览都可承载这些结果。审查者关注视觉和数据变化,而不是对无法阅读的二进制文件直接批准。
自动截图要固定相机、灯光、曝光、背景和引擎版本。否则环境变化会制造无意义差异。
锁与任务系统
锁信息应出现在 DCC或编辑器 内,而不是等保存失败才发现。资产面板可以显示负责人、任务、分支、锁时间和联系方式。
锁最好与任务边界一致:一个人负责角色网格,另一人仍可编辑独立动画和材质。若所有内容嵌在一个源文件里,锁粒度只能粗化,这也是拆分源资产的理由。
长时间锁应自动提醒,但不能在用户仍有未提交修改时自动释放。强制解锁前先联系负责人、保存 Shelve/备份,并留下审计记录。
跨职能合作
技术规则要和美术、策划、程序共同制定。有效流程:
- 用实际失败案例和性能数据说明问题;
- 定义可交付结果与责任边界;
- 先提供本地快速检查和清楚修法;
- 再把同一规则放入 CI 门禁;
- 对合理例外设置负责人和到期时间;
- 统计高频失败,优先改工具而不是反复培训。
冲突不应只靠“谁的职位高”。区分视觉目标、技术约束、排期和工具缺口,用可复现测试讨论取舍。
故障与恢复
恢复先区分“分支指错版本”和“该版本需要的字节丢失”。前者可以从正确历史形成恢复提交,后者必须从另一对象副本或备份取得内容。Git引用与LFS对象分开保存时,备份清单要记录受保护提交及其所有对象OID;保留策略先保护这些OID,再清理不被保留版本引用的对象。只复制Git目录会留下可以浏览历史、却无法打开源资产的备份。
恢复演练在独立环境取得一个发布版本,按清单还原版本元数据、对象存储和所需访问配置,然后核对每个对象的哈希与长度,最后实际导入并构建。若某个OID缺失,停止发布并恢复相同哈希的对象;随手上传同名新文件会产生不同OID,不能修复旧指针。恢复错误提交时保留现有历史,以新提交恢复选定内容及其依赖,再按正常队列验证,避免绕过其他成员已取得的版本关系。
锁遗留单独处理。负责人已离线时,先保存其未提交内容或已有搁置版本,记录交接原因,再由有权限的人解除锁;新负责人从确认的服务端版本开始编辑。自动计时提醒可以暴露久占锁,自动超时释放却可能让两个仍在工作的副本同时获得编辑预期。
仓库迁移也遵循相同的身份链:在镜像中迁移,生成旧提交到新提交的映射,验证发布版本的源字节和依赖;切换时冻结旧库写入、迁移最后增量、验证新入口并通知客户端重新定位。恢复窗口内保留只读旧库和映射。迁移改变的提交身份、外部引用及构建记录必须一起处理,不能只检查最新目录看起来相同。
验证方法
从干净工作区检出指定提交,检查大文件对象实际到位。模拟锁冲突、离线编辑与部分提交,确认源和元数据成组恢复。二进制语义合并以工具支持为条件。
正文给出各工具的编辑、提交和恢复路径;本页没有执行真实服务端迁移、备份恢复或带宽测量。这些运行结果应由上述独立检出和故障场景逐项记录。
相关主题
参考资料
-
Git LFS:Pointer file specification:指针的 version、oid sha256、size 与 clean/smudge 关系。
-
Git LFS track、lock、fsck:跟踪模式、协作锁与对象完整性检查;2026-10-23核读。