介绍

Git 是一个强大的分布式版本控制软件,Unity 则是一个游戏引擎。

由于 Unity 的特性,在使用 Git 对 Unity 项目进行版本控制时要注意很多地方。

策略

同一仓库

因为游戏项目是一个整体,每一个提交都有可能同时改变最终的客户端与服务器,所以建议使用同一个仓库进行版本控制。美术、策划、程序等相关人员在同一个仓库上工作。

多个仓库的版本同步是非常麻烦的,包括自动打包的实现都会异常麻烦且容易出错。

相关内容:合并 Git 仓库 - 狂飙

工作拆分

最好的方式就是不产生冲突问题,从逻辑层面杜绝合并,即将工作拆分为可以同时并行的不同文件中。

大型的场景文件建议使用 Unity 的多场景编辑功能编辑,推送前进行合并。

由于 Git 并没有文件锁定功能,需要人工进行文件锁定的沟通。

分支开发

  • 主线开发
  • 功能分支开发

建议结合使用主线开发与功能分支开发:

  • 普通任务(只有一两次提交)在主线分支上处理
  • 功能作务(需要几次几十次提交)在功能分支上处理

版本选择

建议在项目开始时使用 Git 最新版本,然后遵循版本升级计划,如根据需要每隔半年一年之类的周期进行升级。

Git 新版本往往会带来大量的提升,比如使用 Git LFS 时,老版本只会一个文件一个文件的下载,而新版本会同时开多线程下载文件,速度大大提升。

流程

减少无用合并提交

由于 git pull 默认的行为是 fetch + merge 导致只要本地与远程历史出现分叉就会产生一次合并,而此次合并提交的内容只是本地提交内容的重复。

但是合并提交也是提交,会带来各种各样的改变,而且合并提交中还会处理冲突。而通常我们再处理问题时一般都会忽略合并提交的改动,只会查找改动是由谁的普通提交引入的。

其次 git log 默认的行为是不显示合并前后导致相同内容的提交,即在一个分支中做的提交如果被 revert commit 了,这两次提交合并到当前分支中,在 git log 的输出里看不到这两次提交,需要手动指定 --full-history 才能看见!

推荐使用服务器钩子检查无用合并提交:networm/git-check-useless-merge: Deny push if first parent of last merge commit is not remote branch.

拉取策略

为了保证提交历史是线性的,有两种方式

  • 需要保证拉取更新后提交推送,如果推送时有人插队,需要将提交撤回,再重新拉取提交推送。
  • 可以先提交,拉取时使用变基(pull --rebase)来自动处理。

为了使美术与策略更方便地使用 Git,可以尝试使用变基的方案,那么需要在仓库中设置

1
2
git config pull.rebase true
git config rebase.autoStash true

建议仓库根目录下增加 setup.cmdsetup.command 执行上述命令。

冲突处理

使用上述的变基方案后,遇到冲突要解决二进制文件冲突时,我的他们的 意义相反。

  • 已提交的内容 - 由于 rebase 会先将本地提交暂存,拉取到最新版本,再应用本地提交,所以这时 他们的 才是指我本地提交的版本
  • 未提交的内容 - 由于开启了 rebase.autoStash,那么本地未提交的内容会先储藏,然后再应用,所以这时 他们的 才是指我本地提交的版本

Unity 相关

空目录处理

在 Git 并不会追踪目录改变,所以在检出分支时你需要手动移除目录。 Unity 会为文件与目录生成对应的 .meta 文件。 这些钩子就是用来移除空目录的 .meta 文件来保持一致性。

Unity Git 钩子 - 狂飙

networm/UnityGitHooks: Remove empty directories after git checkout for Unity

meta 文件

将 meta 元信息文件设置为显式可见是很必要的,方便在 Unity 外移动删除资源时不会遗漏。

设置方法:Unity > Edit > Project Settings > Editor 设置 Version ControlModeVisible Meta Files

忽略文件管理

有一个非常好的网站:gitignore.io - Create Useful .gitignore Files For Your Project

建议使用网站提供的安装到命令行的方法使用,因为有些内容如果只是拷贝粘帖会导致内容错误,如 macOS 中有 Icon\r\r 这种,\r\r 在浏览器中会被转换为当前平台的换行符(\n\r\n)从而导致错误。

生成 .gitignore 文件时只建议选择需要的规则,不要添加一堆软件的规则,否则很容易出现 *.meta 被添加到忽略中等类似的问题。推荐只添加 Unity 的忽略文件,其他的规则根据需要手动添加。

序列化设置

设置机器生成的文件为文本

将 Unity 生成的所有文件都改为 Yaml 文本方式保存,可以显示差异同时减少 Git 仓库大小。

差异显示非常重要,可以明确的知道 Unity 对资源做了哪些改动(包括正常对资源的修改与 Unity 升级导致的修改),这样可以更快速地查找错误改动。

设置方法:Unity > Edit > Project Settings > Editor 设置 Asset Serialization ModeForce Text

设置 Git 合并策略

由于 Git 默认对文本文件会进行合并,但是由于 Unity 生成的文本文件逻辑意义上并不是文本,而是二进制数据,所以我们需要让 Git 在合并时不进行文本合并。

设置自动生成的文本文件为不合并策略

.gitattributes

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
*.anim                merge=binary
*.asset               merge=binary
*.bytes               merge=binary
*.controller          merge=binary
*.cubemap             merge=binary
*.flare               merge=binary
*.fontsettings        merge=binary
*.giparams            merge=binary
*.guiskin             merge=binary
*.mask                merge=binary
*.mat                 merge=binary
*.meta                merge=binary
*.mixer               merge=binary
*.overrideController  merge=binary
*.physicMaterial      merge=binary
*.physicsMaterial2D   merge=binary
*.prefab              merge=binary
*.renderTexture       merge=binary
*.shadervariants      merge=binary
*.unity               merge=binary

自行托管

建议使用 GitLab,由于 GitLab 功能完整,支持 Git LFS,更新频繁,很适合企业使用。

大文件管理

由于 Git 会进行仓库压缩,而大的二进制文件压缩是没有意义的,大量的二进制文件体积过大导致每次 Git 进行 repack 时耗费大量无用时间。 大量二进制文件很容易使 Git 仓库超过官方推荐的 1GiB 大小,导致性能下降。

建议使用 Git Large File Storage 来管理。工作原理非常简单,就是将二进制文件替换为文本指针提交到仓库中,在需要的时候从服务器上下载并转换文本指针为二进制文件。

Git 迁移到 Git LFS - 狂飙

使用规范

培训

建议新人进行为期一到两天的培训,可以根据项目需要决定,以下是建议的学习资料,建议按顺序阅读:

进阶

推送

禁止使用 git push --force 覆盖远程分支,包括 master 与功能分支。

master 主线分支是禁止修改历史的,否则会导致他人拉取时出现冲突等问题。

功能分支也不建议修改。

变基

只允许变基(rebase)未推送的非合并提交

由于变基操作会将合并提交退化为普通提交,即多个父提交变为单个父提交。这样会导致合并信息丢失,但是合并的内容存在的问题,在将来再次合并时会出现合并的内容全部冲突。

作者信息

必须要保证每一个人只有唯一的名字与邮箱信息,保证仓库内信息是唯一的可以方便地统计。

GitLab 付费版本有个功能可以检查推送中提交的信息是否与网站中的作者信息一致。

如果有需要可以自行编写推送钩子进行检查,参考:Git - 使用强制策略的一个例子

提交信息

建议规范提交信息,设置提交的格式如:

1
2
3
Issue 编号-提交分类:提交标题

提交详细信息(可省略)

然后通过服务器推送钩子进行检查格式。

时间

所有人员必须开启时间同步选项,保证提交时间是正确的。

服务器必须开启 NTP 同步服务,保证时间是正确的。由于服务器可能会出现时间严重不一致问题,强烈建议开启时间同步服务。

CentOS Linux Install and Configure NTP to Synchronize The System Clock - nixCraft