拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

openclaw 双仓库同步:GitHub main 与 tags 如何完整镜像到 Gitee 并验证一致性

openclaw 双仓库同步:GitHub main 与 tags 如何完整镜像到 Gitee 并验证一致性

1. openclaw 双仓库同步的真实场景:GitHub main 与 tags 镜像到 Gitee 到底难在哪

openclaw 是一个在 GitHub 上活跃迭代的开源项目,很多国内开发者会把它镜像一份到 Gitee,用来加速 clone、方便团队内网拉取,或者单纯作为备份。问题在于:GitHub 那边的 main 分支和 tags 一直在往前走,你第一次同步完之后,过一段时间再想同步,就会发现事情没那么简单——分支可能分叉、tags 可能漏推、远端 refs 对不上。

我自己维护D:\source\openclaw(GitHub 本地克隆)和D:\source\m-openclaw(Gitee 本地克隆)这两个目录有一段时间了。第一次同步的时候觉得挺顺,git push origin --tags一敲就完事。但第二次同步时踩了几个坑:Gitee 那边的 main 因为之前手动改过 README 产生了本地提交,直接git pull会冲突;tags 用普通 push 推不上去,因为有些 tag 指向的 commit 在 Gitee 上根本不存在;还有一次git ls-remote对比时发现两边 tag 数量差了 3 个,排查半天才定位到是--tags和--follow-tags的行为差异。

这篇内容就是把这套流程讲透。核心检索词是 openclaw 双仓库同步,具体要解决的是 GitHub main 分支与全部 tags 如何完整镜像到 Gitee,并且用git ls-remote验证两端 refs 一致性。适合谁看:需要在国内环境维护镜像仓库的开发者,尤其是已经同步过一次、现在要做增量同步的人。

先说清楚一个前提:GitHub 仓库和 Gitee 仓库是两个独立仓库,不是 fork 关系(Gitee 的 fork 机制和 GitHub 不互通)。所以同步的本质是「从一个 remote 拉,往另一个 remote 推」。理解这一点,后面的命令就都好懂了。

整个流程分四块:配置 remote、拉取上游、推送镜像、验证一致性。下面按可复制的顺序展开,每一步都给完整命令和预期输出。

2. TaoToken 前置准备:API Key、Base URL 与模型 ID 三件套怎么配

在讲 git 命令之前,先插一段环境准备。如果你在同步 openclaw 之后要跑它的 AI 相关功能,或者用 Claude Code、Cline 这类工具做代码辅助,需要先把模型接入配好。TaoToken 提供统一的 API 入口,Base URL 是https://taotoken.net/api,配合 API Key 和 Model ID 就能用。

获取 Key 的路径:打开 https://taotoken.net/api-keys ,登录后在控制台创建 API Key。拿到之后不要硬编码在代码里,建议放到环境变量。Windows PowerShell 下可以这样设:

$env:TAOTOKEN_API_KEY = "sk-你的key" $env:TAOTOKEN_BASE_URL = "https://taotoken.net/api"

如果你用的是 Claude Code,配置方式是在 settings 里指定 Base URL 和 Key。Claude Code 的配置文件通常在用户目录下的.claude/settings.json,内容结构如下:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的key", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }

注意这里三个字段缺一不可:Base URL 指向 TaoToken 的 API 地址,Key 用你在控制台创建的那串,Model ID 要写完整模型名。很多人只配了前两个,结果请求报 model not found,就是漏了 Model ID。

如果你用的是 Cline 或者 Roo Code 这类 VS Code 插件,在插件设置里选 OpenAI Compatible,然后填:

配置项值
Base URLhttps://taotoken.net/api
API Keysk-你的key
Model IDclaude-sonnet-4-20250514

Codex 的话,配置写在~/.codex/auth.json里,结构是:

{ "OPENAI_API_KEY": "sk-你的key", "OPENAI_BASE_URL": "https://taotoken.net/api" }

配好之后可以用一个最小请求验证连通性:

curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","messages":[{"role":"user","content":"ping"}]}'

返回里有choices字段就说明通了。这一步和 git 同步本身没直接关系,但如果你同步 openclaw 是为了跑它的 AI 功能,先把接入配好能省后面很多事。更多接入细节可以看 https://taotoken.net/doc 。

3. 可复制配置:git remote 设置与 push --mirror 完整命令

回到 git 同步。先确认两个目录的 remote 配置。进入 Gitee 本地目录D:\source\m-openclaw,查看当前 remote:

cd D:\source\m-openclaw git remote -v

预期输出类似:

origin git@gitee.com:yourname/m-openclaw.git (fetch) origin git@gitee.com:yourname/m-openclaw.git (push)

如果之前已经加过 upstream 指向 GitHub,这里还会多两行 upstream。没加过就执行:

git remote add upstream git@github.com:openclaw/openclaw.git

如果报remote upstream already exists,说明加过了,跳过即可。想确认 upstream 指向对不对:

git remote get-url upstream

接下来拉取上游的 main 和全部 tags。这里有个关键点:git fetch upstream默认只拉分支,不拉 tags。要拉 tags 必须显式加--tags:

git fetch upstream git fetch upstream --tags

执行完你会看到类似输出,列出新增的 tag:

From github.com:openclaw/openclaw * [new tag] v1.2.0 -> v1.2.0 * [new tag] v1.2.1 -> v1.2.1

现在本地已经有了 GitHub 的最新 main 和全部 tags。接下来同步 main 分支。先切到 main:

git checkout main

然后有两种策略。如果 Gitee 仓库没有独立改动,直接硬重置到上游,最干净:

git reset --hard upstream/main

如果 Gitee 仓库有独立提交(比如你改过 README),硬重置会丢掉这些改动。想保留的话用 merge:

git merge upstream/main

merge 可能产生冲突,需要手动解决。实测下来,镜像仓库最好保持「只读」状态,不要在上面做独立改动,否则每次同步都要处理冲突,很烦。

main 同步好之后推送到 Gitee:

git push origin main git push origin --tags

如果 Gitee 的 main 和本地历史不一致(比如之前硬重置过),普通 push 会被拒绝,需要加--force:

git push origin main --force

注意--force会覆盖远端历史,只在你确认 Gitee 仓库没有需要保留的独立提交时用。

还有一种一步到位的做法:用push --mirror。这个命令会把本地所有 refs(分支、tags、甚至 remote-tracking refs)原样推到目标仓库,适合做纯镜像:

git push --mirror git@gitee.com:yourname/m-openclaw.git

但--mirror有个副作用:它会删除目标仓库上本地不存在的 refs。也就是说,如果 Gitee 上有本地没有的分支,会被删掉。所以用之前一定要确认本地是完整的镜像源。日常增量同步我更推荐分开推 main 和 tags,可控性更强。

如果你想把 GitHub 的 main 直接推成 Gitee 的 main,也可以用 refspec 显式指定:

git push origin upstream/main:main --force git push origin --tags

这样不用先 checkout 到 main,适合脚本化。

4. 验证请求与成功结果:用 git ls-remote 对比两端 refs

推完之后必须验证,不然你永远不知道 tags 是不是真的全了。最直接的工具是git ls-remote,它列出远端的所有 refs 和对应的 commit SHA。

先看 GitHub 端的 main 和 tags:

git ls-remote upstream refs/heads/main git ls-remote --tags upstream

再看 Gitee 端:

git ls-remote origin refs/heads/main git ls-remote --tags origin

对比两边的 main SHA,应该完全一致。比如 GitHub 返回:

a1b2c3d4e5f6... refs/heads/main

Gitee 也应该是同一个 SHA。如果不一样,说明推送没成功或者推的不是同一个 commit。

tags 的对比稍微麻烦一点,因为git ls-remote --tags会同时列出轻量 tag 和附注 tag 的解引用行(带^{}后缀)。附注 tag 会有两行,一行是 tag 对象本身的 SHA,一行是它指向的 commit SHA。对比时要注意这一点。

更省事的做法是把两边输出排序后 diff。PowerShell 下可以这样:

git ls-remote --tags upstream | Sort-Object | Out-File gh-tags.txt git ls-remote --tags origin | Sort-Object | Out-File gitee-tags.txt Compare-Object (Get-Content gh-tags.txt) (Get-Content gitee-tags.txt)

如果Compare-Object没有输出,说明两边 tags 完全一致。有输出的话,=>表示只在 Gitee 有,<=表示只在 GitHub 有。实测下来,最常见的差异是 GitHub 新增了 tag 但没同步过来,重新执行git fetch upstream --tags和git push origin --tags即可。

还有一个快速统计 tag 数量的办法:

(git ls-remote --tags upstream | Measure-Object).Count (git ls-remote --tags origin | Measure-Object).Count

两个数字相等不代表内容一致(可能有同名不同 SHA 的情况),但数量不等一定有问题,可以先用这个做粗筛。

验证 main 分支的另一种方式是比对 commit SHA:

git rev-parse upstream/main git rev-parse origin/main

两个输出应该相同。如果不同,检查是不是推送时用了错误的 refspec。

成功的结果长这样:main 的 SHA 两端一致,tags 列表 diff 为空,tag 数量相等。到这一步,openclaw 的 GitHub main 与全部 tags 就完整镜像到 Gitee 了。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth 报错对照

同步过程中和接入过程中会遇到一些典型报错,这里集中列一下。

git push 报! [rejected] main -> main (non-fast-forward)

这是最常见的一个。原因是 Gitee 的 main 有你本地没有的提交,git 拒绝覆盖。解决方式二选一:如果那些提交不要了,用git push origin main --force;如果要保留,先git pull origin main合并再推。镜像仓库场景下通常直接 force。

git fetch upstream --tags 报couldn't find remote ref

检查 upstream 的 URL 是否正确,以及 GitHub 仓库是否真的存在这个 tag。有时候 tag 被上游删了,本地还留着,git fetch --prune --tags可以清理。

git ls-remote 返回空

说明 remote 名字写错了,或者没有网络权限。先git remote -v确认名字,再git ls-remote upstream不带参数看能不能列出东西。

接入侧报 401 Unauthorized

API Key 错了或者没带上。检查请求头是不是Authorization: Bearer sk-xxx,注意 Bearer 后面有空格。Key 如果泄露了要去 https://taotoken.net/api-keys 重新生成。

报 local proxy failed 或 connection refused

本地网络配置问题。检查是不是设了HTTP_PROXY/HTTPS_PROXY环境变量指向了一个不可用的地址。清掉这些变量再试:

Remove-Item Env:HTTP_PROXY -ErrorAction SilentlyContinue Remove-Item Env:HTTPS_PROXY -ErrorAction SilentlyContinue

返回体里 reading choices 报错或 choices 为空

通常是 Model ID 写错了,或者请求体格式不对。确认 model 字段是完整模型名,messages 是数组且每项有 role 和 content。用最小请求体测试,排除参数干扰。

OAuth 相关报错

Claude Code 或某些工具会走 OAuth 流程,如果配置了 Base URL 又走了 OAuth,可能冲突。检查 settings.json 里是不是同时存在 OAuth token 和 API Key 配置,保留一种即可。

push --mirror 之后 Gitee 上的分支消失了

这是--mirror的正常行为,它会删除目标端本地不存在的 refs。如果误删了,从 GitHub 重新 fetch 再推一次。日常同步建议别用--mirror,用分开推的方式。

tags 推上去了但指向的 commit 在 Gitee 上不存在

这种情况发生在 tag 指向的 commit 不在任何分支上时。git push origin --tags会尝试推送 tag 及其指向的对象,一般能成功。如果失败,先确保 main 已经推上去,再推 tags。

排查思路总结成一句:先确认 remote 配置,再确认 fetch 到了什么,最后确认 push 推了什么,每一步都用git ls-remote或git log看实际状态,别靠猜。

6. 语义一致 CTA:同步完成后继续用 openclaw 做开发

镜像同步只是第一步。openclaw 同步到 Gitee 之后,国内团队拉取速度会快很多,接下来就是拿它做实际开发。如果你在开发过程中需要 AI 辅助写代码、补测试、做 code review,可以把模型接入配起来。

需要 API Key 和接入文档的,直接去 https://taotoken.net/api-keys 创建 Key,配置细节看 https://taotoken.net/doc 。想先试试模型对话效果,可以打开 https://taotoken.net/model-chat 直接聊几句,确认模型可用再往工具里配。

如果是长期做编码或者跑 Agent 任务,Coding Plan 更划算,入口在 https://taotoken.net/coding-plan 。Claude Code 用户可以直接参考 https://taotoken.net/claude-code 的接入说明,把 Base URL、Key、Model ID 三件套填进去就能用。

最后留一个实用习惯:把同步命令写成一个 PowerShell 脚本,每次要同步时跑一遍,省得记命令。脚本大概长这样:

cd D:\source\m-openclaw git fetch upstream git fetch upstream --tags git checkout main git reset --hard upstream/main git push origin main --force git push origin --tags git ls-remote --tags upstream | Sort-Object | Out-File gh-tags.txt git ls-remote --tags origin | Sort-Object | Out-File gitee-tags.txt Compare-Object (Get-Content gh-tags.txt) (Get-Content gitee-tags.txt)

跑完看 Compare-Object 有没有输出,没有就说明这次同步干净利落。这个脚本我用了几个月,比每次手动敲命令靠谱得多。

返回列表