
先给结论RN for OpenHarmony 的工程从本地搬到 AtomGit 这台远程仓库核心不是“git push”这一步而是把工程里“该提交的提交、该忽略的忽略、该配的环境提前配好”。我第二天做的就是把这件事彻底捋顺了顺便把第一天留下的一些隐患也一起收拾干净。今天这篇学习笔记会按我实际操作的顺序来写先讲清楚远程同步到底在同步什么、为什么会踩白屏这类坑再给出一份能直接抄的.gitignore配置然后是 AtomGit 建仓、SSH 公钥、首次 push 和后面协作拉取的全流程最后是我这两天遇到过的典型问题和排查经验。如果你正在用 React Native 做 OpenHarmony 应用或者准备把本地工程交给团队一起维护这篇笔记刚好可以省掉你不少试错时间。1. 先想明白RN for OpenHarmony 工程做远程同步到底在同步什么1.1 远程同步的基础模型很多人第一次用 Git 远程仓库时脑子里只有“push 上去”“pull 下来”这两个动作。但实际操作中本地的代码会经过四个区域工作区你正在编辑的文件、暂存区git add 后的地方、本地仓库git commit 后的记录、远程仓库AtomGit/GitHub 这类托管平台。这个模型对 RN for OpenHarmony 项目尤其重要因为这类工程的提交单位不只是“代码”还有依赖声明、构建脚本、原生工程配置等。第一天我建完本地工程后第一反应是“先 push 上去再说”结果发现 oh_modules、node_modules、.hvigor 之类的目录动辄几百 MB真要全部推上去不仅浪费时间还会把仓库搞得非常臃肿。所以我第二天做的第一件事不是 git init而是先做“工程体检”看清楚一个 RN for OH 工程里哪些是源码、哪些是构建缓存、哪些是机器生成的东西。理清这个后面所有操作都不会跑偏。1.2 RN for OH 工程的特殊性JS 与原生壳并存的混合仓库React Native for OpenHarmony简称 RNOH和普通 React Native 工程最大的区别是它的工程里不仅有 JS/TS 业务代码还有一个完整的 OpenHarmony 原生工程通常是ohos目录里面是 DevEco Studio 工程结构。这个原生壳负责加载 JavaScript 引擎、创建原生组件、桥接 ArkUI 和 RN 运行时。这意味着一个仓库里同时存在两套生态npm 生态package.json、node_modules、babel.config.js、metro.config.js 等负责 JS 侧的转译、打包。OpenHarmony 生态oh-package.json5、hvigorfile.ts、build-profile.json5、entry 模块等负责鸿蒙原生侧的编译、签名和安装。做远程同步时这两套生态的“锁文件”都非常重要。npm 侧是 package-lock.json 或 yarn.lockOH 侧是 oh-package-lock.json5。如果你不把锁文件提交到远程队友拉下来后安装依赖就是“撞大运”版本不一致直接导致编译行为不同。1.3 同步前后要守住的底线两天实践下来我给自己定了三条“底线”你也可以直接复用构建产物绝不入库。node_modules、oh_modules、build、.hvigor、.cxx 这些要么是依赖、要么是缓存删了能自动生成的都不要提交。本地个性化配置不入库。签名配置文件如 .cer、.p7b、.p12 这类证书文件、本地路径相关的 local.properties 之类只留在本地远程仓库一律忽略。锁文件必须入库。package-lock.json、oh-package-lock.json5 这两类文件要提交保证团队所有人依赖版本一致。这三条守住了远程同步基本不会出大乱子。后面常见的白屏、编译不了、依赖冲突很多都是因为有人违反这三条。2. 开工前的工程体检哪些文件进仓库哪些必须请出2.1 RN for OH 项目与普通 RN 项目的目录差异我第一天是从社区模板创建的项目目录和普通 RN 项目不一样的地方在于它有ohos这样一个原生壳目录而且项目根目录多了 oh-package.json5、hvigorfile.ts、build-profile.json5 这些文件。普通 RN 项目大家都会忽略 node_modules、android/build、ios/Pods。而 RN for OH 项目除了 node_modules 之外还要重点识别几个 OH 侧的目录ohos/.hvigorhvigor 构建缓存删了会重新生成。ohos/oh_modulesOpenHarmony 侧依赖安装目录类似 node_modules。ohos/.cxxNative C 编译产物。ohos/build、ohos/entry/build应用构建产物。.idea、.vscode等 IDE 配置视情况忽略。另外如果你的项目里有ohos/entry/src/main/resources/base/profile/main_pages.json这类路由配置以及module.json5这些是源码需要提交。2.2 一份能直接抄的 .gitignore 模板在写.gitignore时我踩了一个小坑只忽略了根目录的oh_modules但实际生成目录在ohos/oh_modules下结果第一次 git add 差点把这些大目录带进去。所以忽略规则一定要写清楚路径或者用不带斜杠的目录名让它匹配任意层级。这是我第二天整理完、目前在用的模板可以直接抄# 依赖目录 node_modules/ oh_modules/ **/oh_modules/ # 构建产物 build/ **/build/ .cxx/ **/.cxx/ .hvigor/ **/.hvigor/ ohos/.hvigor/ # IDE 与系统文件 .idea/ .vscode/ *.iml .DS_Store # 本地签名与配置文件 local.properties *.cer *.p7b *.p12 *.jks *.keystore # 日志与临时文件 *.log npm-debug.log* temp/ tmp/ # 可选如果不想提交 JS bundle # ohos/entry/src/main/resources/rawfile/entry.bundle需要注意entry.bundle这条我默认是注释掉的。因为 release 包如果需要内置 bundle就把它提交如果你们走 Metro dev server 远程加载则可以忽略。这个要看团队构建方案没有统一答案。另外.gitignore生效的前提是“文件还没被 git 跟踪”。如果你之前已经误提交了 node_modules后面再在 .gitignore 里加规则也不会自动移除必须先执行git rm -r --cached把文件从暂存区/版本库移除然后提交一次“清理”记录。这个操作后面第 5 节会详细说。2.3 推送前先确认 git 身份这个坑不算大但很烦人第一天我直接git commit结果提交记录里显示的用户名和邮箱是全局配置里的旧账号推到 AtomGit 后贡献列表里完全对不上人。所以在首次提交前最好在项目目录里确认一下 git 身份git config user.name git config user.email如果输出为空或者不是你想要的身份就在项目内设置一次避免影响全局配置git config user.name yourname git config user.email youexample.com如果你不确定理想用户名写什么AtomGit 首页右上角头像里的个人资料页有你绑定的用户名保持一致就好。这个身份是写在本地仓库里的不会跟着工程跑到远端但会影响提交记录作者信息。3. AtomGit 远端准备建仓库与 SSH 公钥配置3.1 在 AtomGit 上创建一个空仓库我这里用 AtomGit 的原因有两个一是国内访问速度快不需要额外的网络配置对日常 push/pull 很友好二是 OpenHarmony 相关的不少官方 SIG 仓库也能在平台上找到素材很适合顺手把本地工程和社区项目关联起来。登录 AtomGit 后在个人主页找到“新建仓库”入口。创建页面有几个选项需要按场景选择仓库名称建议和本地工程名保持一致比如rn-oh-demo降低记忆成本。公私属性个人学习用就选私有后面如果要给他人参考再改成公开。初始化选项这一步非常关键我这里建议“全部不勾选”。也就是不要自动生成 README、.gitignore 和 License。因为我们本地已经有完整工程如果远端自动生成了 README首次 push 时会出现“远端和本地各自有提交”的历史分叉处理起来要多一层 merge 或 rebase很没必要。创建完成后AtomGit 会进入一个空仓库页面。页面上通常会给出两种常见操作方式HTTPS 地址和 SSH 地址。我优先选 SSH下面讲原因。3.2 生成 SSH Key 并绑定到 AtomGitHTTPS 方式也可以 push但每次都输用户名和密码或 Token而且 Token 过期后又要重新配置。SSH 方式是一次性把公钥放到平台后面所有仓库都免密推送干净省事。如果你之前生成过 SSH Key可以直接复用不用重新生成。检查方法ls -al ~/.ssh如果看到id_ed25519.pub或id_rsa.pub在终端执行cat ~/.ssh/id_ed25519.pub直接复制内容即可。如果没有就执行ssh-keygen -t ed25519 -C youexample.com一路回车默认生成到~/.ssh/id_ed25519下。注意如果之前机器上已经有同名私钥文件会被覆盖。如果你不确定建议先手动确认~/.ssh下已有文件类型再决定是否重新生成。然后把公钥内容复制到 AtomGit 的“个人设置 → SSH 公钥”页面。添加时会给一个标题比如 “my-mac”可以方便地辨认是哪台机器的密钥。3.3 验证 SSH 连通性添加完公钥后先验证一下能不能连上 AtomGit再回来推代码。在我实际操作中最简单的验证方式是ssh -T gitatomgit.com如果配置正常会返回类似“Welcome”的提示信息。如果返回权限拒绝首先检查公钥是否复制完整开头能不能看到算法名和邮箱其次确认当前 ssh-agent 是否加载了私钥。验证通过后再用 AtomGit 提供的 SSH 仓库地址形如gitatomgit.com:yourname/rn-oh-demo.git执行后续操作。这里提前说明如果你公司或本地的防火墙屏蔽了 22 端口SSH 可能不通这种情况改用 HTTPS 地址也能同步只是每次操作需要带上认证信息。4. 本地仓库初始化与首次推送全流程4.1 初始化仓库并统一分支名在项目根目录打开终端执行git init不同版本的 Git 初始化仓库后默认分支名可能是master也可能是main。为了避免和仓库远端默认分支不一致最好在 init 之后马上统一分支名。我习惯用 maingit branch -M main这条命令即便当前仓库已经有 commit 也可以执行作用是“把当前分支重命名为 main”。如果在第 1 步忘了执行等到关联远端后才发现本地和远端分支名不一致也可以在任何时候用git branch -M main修正。一个常见疑问到底用 main 还是 master其实没有强制规定关键是本地和远端保持一致。AtomGit 上面新建空仓库时通常默认分支是 main所以本地也统一为 main 最省心。4.2 首次 add 与 commit确认.gitignore生效之后先执行git status查看文件状态。这一步很多人会跳过但我建议每次都看一眼重点确认没有体积巨大的目录出现在“待提交”列表里。确认无误后执行暂存和提交git add . git commit -m init: 导入 React Native for OpenHarmony 基础工程提交信息这里稍微讲究一点。因为这是第 2 天迭代如果你之前已经有 Day1 的本地版本建议在信息里写清楚当前状态比如“导入完成本地构建的工程”这样后面回看历史时能一眼看出这个版本能做什么、不能做什么。有一点要注意如果执行git add .后git status 里没看到任何变化先检查你是否在项目根目录执行的命令。另一个可能原因是当前文件已经被.gitignore全量忽略这种情况可以用git add -f强制添加某个明确需要入库的文件但正常情况下不建议这么干可能意味着你的忽略规则太宽了。4.3 关联远端并执行首次 push回到 AtomGit 空仓库页面复制 SSH 地址然后执行git remote add origin gitatomgit.com:yourname/rn-oh-demo.git git remote -vgit remote -v的作用是确认远端地址是否配置正确。如果你输入后发现 URL 写错了可以用git remote set-url origin重新设置。这个命令在后续协作中很常用值得记一下。第一次推送时执行git push -u origin main-u参数的作用是把本地 main 分支和远端 main 分支关联起来。推送成功后后续再执行git push时就可以直接省略分支名了。首次推送如果没有带-u也能推送成功只是本地不会自动记住“上游分支”后面你执行git pull时会提示 “no tracking information”。首次 push 时如果 AtomGit 仓库页面你看不到任何文件先等一两秒刷新可能只是缓存。如果长时间空白多半是 push 报错被中断了回到终端看报错信息。4.4 推完之后的本地验证与协作拉取策略第一版推上去后我还做了一次“反向验证”在项目另外一个临时目录里通过git clone把仓库拉下来然后尝试本地编译一次。这个验证看起来很笨但非常值。它能一次性确认两件事我提交的文件是否完整到可以独立构建我的.gitignore是否误伤了一些必须入库的源码文件。拉取命令git clone gitatomgit.com:yourname/rn-oh-demo.git如果 clone 下来的工程能正常执行依赖安装、构建那本地首次推送就成功了。如果构建报缺少某某文件说明你之前忽略了不该忽略的源码需要回到原工程补提交。等团队协作开始后每次开始工作前建议先git pull --rebase这里挂--rebase的好处是本地如果有未推送的提交rebase 会把本地的提交“接续”到远端最新提交后面提交历史是一条直线不会出现一堆 “Merge branch” 节点。如果直接git pull默认 merge多人协作一段时间后提交历史会变得很乱。5. 远程同步中的常见问题与排查记录5.1 白屏问题clone 下来或重新编译后页面全白这个问题在搜索结果里也高频出现确实很典型。现象是本地工程 push 到远端后队友 clone 下来依赖装好、编译也成功但应用启动后白屏。我在 Day1 也遇到过类似情况。根因多半不是远程同步本身而是 JS 侧的资源没到位。RN for OH 应用在启动时会从本地加载 JS Bundle或连接 Metro dev server。如果你构建的是 release 包但 bundle 没有生成或没有打进应用资源目录页面当然全白。排查思路按三步走确认启动模式。debug 模式下检查 Metro 是否启动、RN OH 工程里的 dev server 地址是否配置正确。确认 bundle 路径。release 模式下确认构建脚本是否执行了 bundle 打包产物是否放在了工程预期的 rawfile 目录下。如果本地远程同步后首次构建白屏优先执行一次“干净构建”删除ohos/entry/build、ohos/.hvigor、ohos/oh_modules重新安装依赖再构建。还有一个隐蔽原因是.gitignore把 bundle 文件忽略掉了。如果你们的工程是“先打 bundle 再提交”但 .gitignore 恰好忽略了*.bundle那队友 clone 下来后就没有 bundle 文件启动时自然白屏。这种情况建议在仓库里保留 bundle 文件的提交或者统一采用 Metro 模式开发避免文件缺失问题。5.2 node_modules 或 oh_modules 被误提交后的后悔药如果你刚开始没配好 .gitignore已经把这些大目录推上去了不用担心Git 是有后悔药的。核心思路是把文件从 Git 跟踪中移除但保留在本地磁盘。git rm -r --cached node_modules git rm -r --cached ohos/oh_modules git add . git commit -m chore: 移除误提交的依赖目录改用 .gitignore 管理 git push注意--cached参数非常关键。如果没有这个参数git rm 会把本地文件也删掉带上了之后它只会在暂存区里标记“移除跟踪”磁盘文件还在。清理完之后建议在 AtomGit 仓库页面看下仓库体积。如果之前已经推上去了很大体积历史提交里还是会有这些大文件的记录只是新提交后仓库体积不再继续增长。要彻底清理历史记录需要git filter-repo这类重写历史的工具涉及团队协作时要格外谨慎我建议个人学习阶段先不碰等团队规范定了再统一处理。5.3 SSH 权限、远端关联失败与大小写问题这里把几个高频报错集中说一下。情况一推送时提示 Permission denied (publickey)原因通常有三个公钥没有绑定到 AtomGit公钥绑定了但用的是另一台机器的私钥ssh-agent 没有加载对应私钥。排查顺序是先用 3.3 节的命令验证连通性再看本地~/.ssh下私钥文件名是不是默认的id_ed25519。如果私钥文件名自定义过需要在~/.ssh/config里显式配置 key 路径。情况二remote origin already exists执行git remote add origin xxx时报这个错说明之前已经配过 origin 了。此时不要硬删先看下原来的地址是不是写错了git remote get-url origin如果确实需要改成新地址用git remote set-url origin gitatomgit.com:yourname/rn-oh-demo.git情况三文件名大小写引来的问题在 OpenHarmony 原生工程里有些资源文件要求字母大小写敏感。比如main_pages.json里配置的页面路径如果实际文件是Index.ets而配置写的是index.ets本地开发可能正常但 clone 到别的平台后会因为文件系统对大小写不敏感/敏感的差异导致构建失败。这个问题和 Git 也有关系Git 默认对大小写不敏感如果你在本地重命名了文件只改大小写git 可能不会记录这个变化。解决方式是设置git config core.ignorecase false然后重新检查文件名和引用路径确保远端仓库里的大小写与源码引用完全一致。5.4 多人协作原生代码和 JS 模块的合流策略RN for OH 项目里最活跃的部分通常是 JS/TS 业务代码但ohos/entry/src/main/ets下面也会有原生逻辑比如自定义原生组件、权限申请、生命周期管理。团队协作时JS 侧和原生侧往往由不同人维护容易冲突。我的建议是每一次改动尽量保持“单一职责”。原生模块的修改和业务页面变化分开提交不要把一堆不相干的文件塞进同一个 commit。如果团队里有专门的原生开发者可以让原生模块与 JS 业务代码在目录结构上隔离比如原生自定义组件放在ohos/entry/src/main/ets/components下业务页面放src下。这样即使同一仓库内不同人改不同目录冲突概率也低。一旦出现冲突优先以“最近一次验证可编译”的版本为基准手动合并后再本地构建验证。不要直接采用任意一方的删除。RNOH 场景下JS 侧改动往往不影响原生构建但原生侧改动有可能会影响 JS 侧的接口类型定义。所以原生侧 PR 尽量附一句“对 JS 侧的影响说明”能省去团队里很多沟通成本。5.5 真机侧的小提醒hdc 连接与设备信息核对如果你和我一样最终要在开发板上跑rk3568、rk3588 这类远程同步后的构建部署还有一个容易忽略的环节确认 OpenHarmony 设备连接正常。OpenHarmony 真机调试用的是 hdc 工具类似 Android 的 adb。在构建并安装到开发板之前先执行hdc list targets确认输出里有目标设备。如果有多个设备构建脚本或 DevEco Studio 需要明确指定目标设备否则可能装到错误设备上。另外签名和调试需要用到 UDID 和 serial。获取方式一般是hdc shell bm get -u这个信息在设置自动签名的时候会用到。如果配置了错误的设备标识应用安装到板子上可能启动失败表面上很像“代码问题”实际是签名问题。拉完远端代码、构建部署失败时记得把这一步也纳入排查范围。6. 写在最后几个让我少走弯路的小习惯Day2 的实操走下来我最大的感受是远程同步这件事真正费时间的不是那几个 git 命令而是“仓库里应该有什么”的判断。这里沉淀出几个我以后会一直沿用的小习惯你可以当做一个 checklist每次git add .之前先跑一次git status花十秒看看有没有不该出现的目录。项目生成后第一时间写好.gitignore不要在构建成功后才补因为那时你已经生成了大量缓存文件。首次提交前确认全局 git 身份确实是自己想要的不然提交历史里留下错误作者改起来很麻烦。每次准备提交前先在本地跑一次能过的最小构建。我在 Day2 就吃过一次亏改了 README 觉得“没风险”直接 push结果队友 clone 后因为没安装 hvigor 依赖直接构建失败。后来我把“构建验证”作为提交前的一个强制步骤。远端用的仓库地址能选 SSH 就选 SSH。虽然配置 Key 多花几分钟但后面每次 push/pull 都值回来。不要为了追求“华丽的提交历史”频繁 rebase 一个已经推到远端的公共分支。个人学习分支随便折腾合作分支要克制。这轮把本地工程和 AtomGit 远程仓库打通之后后续迭代就舒服多了换机器、备份、给朋友参考、联调协作都从“这坨代码只在我电脑上”变成了“随时可以拉取、构建、验证”的状态。下一步我准备在工程里继续加原生组件模块到时候再把这部分实践单独整理一篇出来。