这篇文章想回答的不是“怎么 push 一次代码”,而是“当我对 AI 说,把这个文件夹发到我的 GitHub 上吧,它中间到底经历了什么,又为什么会卡住,最后为什么还得用
gh?”
前几天我给 AI 下了一个看起来很简单的指令:把 D:\Github\MyPet 这个文件夹推到我的 GitHub 仓库区里,顺便还要安装一下 github-mcp-server。
表面上看,这像是一个“执行几条命令”的问题。但真正走下来我才发现,这里面至少同时涉及了四层能力:
- 本地文件系统和项目状态
- 本地 Git 仓库管理
- GitHub 平台上的远程仓库创建与认证
- AI 工具如何通过 MCP 访问 GitHub 能力
如果不把这四层分开,几乎一定会把 git、gh、GitHub MCP Server 以及 OpenCode 之间的关系混成一团。本文就按一次真实执行链路,把这件事拆开讲清楚。
一、从一句“帮我推到 GitHub”开始,系统到底先做了什么
当我发出“把这个文件夹推到 GitHub”这种指令时,AI 通常不会立刻就执行 git push。在这次场景里,更稳妥的做法是先做一轮上下文确认。
这一步通常会先回答几个问题:
- 目标文件夹是不是一个现成的项目?
- 它是不是已经是一个 Git 仓库?
- 远程仓库是否已经存在?
- 本机是否已经具备 GitHub 身份认证?
- 用户说的“安装 github-mcp-server”,到底是装成什么形态?
也就是说,系统先要判断:这是一个“已有仓库的推送问题”,还是一个“从零建仓并发布”的问题。
在我这次的实际过程里,第一轮检查得到的结论是:
D:\Github\MyPet一开始并不是一个现成的 Git 仓库- 目录最初也不是一个完整的前端工程,我还先在里面初始化了一个 React 项目
- 本机当时没有安装
gh - 也没有现成可用的 GitHub 登录态可以直接完成仓库创建
这就决定了后续的动作不适合直接进入 push,而是要先补全前置条件。
二、真正的第一步不是 push,而是把文件夹变成一个“可发布对象”
很多人会把“推到 GitHub”理解成一个单动作,但实际上它至少包含两段:
- 先把本地目录整理成一个 Git 仓库
- 再把这个 Git 仓库连接到 GitHub 上的远端仓库
如果目录连 .git 都没有,那它根本就还不是一个能被 Git 推送的对象。
所以我当时真正做的事情是:
1)检查目录状态
先确认 MyPet 目录里有什么、是不是已有项目、是不是已有 .git。
2)如果需要,先把项目补完整
因为 MyPet 目录一开始几乎是空的,我先在里面初始化了一个 Vite + React 项目,写好了一个宠物店首页,并完成了依赖安装、构建和启动验证。
这一步的意义不是“顺手多做点事”,而是为了让这次发布出去的内容符合我自己的目标:它不是一个空目录,而是一个真实可运行的工程。这属于这次任务的质量要求,不是发布到 GitHub 的唯一技术前提。
3)初始化 Git 仓库
确认项目成型以后,才执行 git init,让目录成为一个真正的本地 Git 仓库。
4)创建第一条提交
在常规工作流里,通常要先有至少一次提交,后续的远端仓库才有明确可推送的内容。
换句话说,GitHub 托管的不是“某个裸文件夹”,而是 Git 仓库内容;用户最终浏览到的,是某次提交对应的文件树和历史。
三、为什么在这次场景里,引入 gh 最直接
这里是整件事里最容易被误解的一点。
很多人会问:既然已经有 git 了,为什么后面还要装 gh?直接 git push 不就行了吗?
答案是:git push 的前提,是你已经有一个远端仓库,并且本机具备能向这个远端认证的凭据。
而我这次遇到的问题,恰恰不是本地 Git 的问题,而是:
- GitHub 上还没有对应的新仓库
- 本机也还没有可用的 GitHub CLI 登录态
在这次场景里,只靠 git 不够。
gh 到底是什么
gh 是 GitHub CLI(GitHub 官方命令行工具)。
它和 git 的角色并不一样:
git主要处理本地仓库、提交、分支、diff、push/pull 这些 Git 协议层面的事情gh主要处理 GitHub 平台层面的事情,比如登录 GitHub、创建 GitHub 仓库、查看 PR、创建 issue、管理 release 等
最关键的是,gh repo create 可以直接在 GitHub 上创建一个新仓库,而 gh auth login 可以让这台机器获得对 GitHub 的身份认证。
所以到了“我要把一个本地仓库发布到 GitHub,但 GitHub 上对应仓库还不存在”的场景时,gh 就成了最直接、最顺手的桥。当然,这并不意味着它是唯一办法;网页创建仓库、API、PAT 或 SSH 也能完成类似目标。
一句话概括:
git负责“我本地有什么”,而在这次场景里,gh负责更方便地处理“GitHub 上要不要有这个仓库,以及我有没有权限和它说话”。
四、这次流程真正卡住的点,不是 Git,而是认证
这一轮执行里最有代表性的地方,不是某条命令本身,而是中间发生的“卡住”。
系统当时做了这些事情:
- 安装了 GitHub CLI
- 初始化了本地仓库
- 完成了本地提交
- 准备创建远程仓库并推送
然后在这一步停住了。
原因非常明确:
gh虽然安装好了- 但是
gh auth status显示当前没有登录 GitHub
这意味着:
- 可以继续做本地 Git 操作
- 但在当前机器还没有可用 GitHub 凭据的前提下,不能替我在 GitHub 上创建新的远程仓库
- 也不能在这个前提下安全地把代码推到我的 GitHub 账号下
这也是为什么 AI 后来一直反复强调:
现在不能继续自动完成最后两步,不是因为流程没想清楚,而是因为缺少 GitHub 身份认证这个外部前置条件。
这件事特别值得记住,因为它说明了一个很重要的工程常识:
自动化流程失败,很多时候不是“命令不会写”,而是“边界条件没有满足”。
五、那 github-mcp-server 又是什么?它和 gh 是一回事吗?
不是一回事,而且它们解决的根本不是同一层问题。
GitHub MCP Server 是什么
GitHub MCP Server 是 GitHub 官方提供的一个 MCP Server。
它的作用不是“替代 git”,也不是“替代 gh”,而是把 GitHub 的平台能力包装成 MCP 语义下可以被 AI 工具调用的能力。MCP Server 通常可以暴露的形态包括:
- tools
- resources
- prompts
也就是说,GitHub MCP Server 的定位是:
让 AI 宿主(host)可以通过 MCP 协议访问 GitHub 的能力。
它面向的核心对象不是“手工敲命令的人”,而是“会调用工具的 AI 系统”。
那为什么我还要安装它
因为这是另一个独立需求:你不只是想把代码推到 GitHub,还希望 AI 以后可以通过 GitHub MCP Server 去理解、操作或读取 GitHub 里的内容。
比如以后它可以做这些事:
- 读取仓库信息
- 处理 issue 和 PR
- 查询代码文件内容
- 做一些 GitHub 平台侧的自动化操作
但要注意,这条链路和本地 shell 里的 git push 并不是同一条链路。
六、OpenCode 是怎么和 GitHub MCP 交互的
这部分如果不讲清楚,最容易产生一种误解:
“既然 OpenCode 已经能接 GitHub MCP,那是不是以后连
gh都不需要了?”
答案是:不能这么简单理解。
先把角色分开:
1)OpenCode 是 host
OpenCode 这类系统,本质上是一个 MCP Host。
Host 的职责通常包括:
- 读取 MCP 配置
- 连接本地或远程的 MCP Server
- 把 Server 暴露出来的 tools/resources/prompts 提供给模型使用
- 在模型需要的时候,负责发起调用并收回结果
2)GitHub MCP Server 是 server
它提供的不是“本地命令”,而是“协议层可调用能力”。
举个更直观的比喻:
- OpenCode 像一个调度台
- GitHub MCP Server 像一个对接 GitHub 的专用服务窗口
- 模型需要 GitHub 能力时,会由 OpenCode 代表模型去敲这个窗口
3)交互流程到底是什么样
如果把这条链路写成步骤,大概是这样:
- OpenCode 启动
- 读取 MCP 配置
- 连接 GitHub MCP Server(本地或远程)
- 获取该 server 提供的 tools/resources/prompts
- 当模型在对话里需要 GitHub 能力时,OpenCode 发起 MCP 调用
- GitHub MCP Server 通常会代表 AI 去访问 GitHub API 或平台能力,并把结果返回给 OpenCode
这条链路里,OpenCode 做的是宿主管理和工具调度,GitHub MCP Server 做的是GitHub 能力暴露。至于模型什么时候能直接用到这些能力,还会受到宿主实现、权限配置和审批策略的影响。
七、为什么说 gh 和 GitHub MCP 不是替代关系,而是两条不同路径
这件事可以用一句非常实用的话概括:
gh更像“人在终端里直接操作 GitHub”,GitHub MCP 更像“AI 在协议层里调用 GitHub”。它们有能力重叠的地方,但接口形态并不相同。
两者都能碰到 GitHub,但它们解决的问题并不相同。
gh 更适合的场景
- 登录 GitHub
- 创建一个全新的 GitHub 仓库
- 和本地 Git 推送链路打通
- 在 shell 脚本里完成 GitHub 平台操作
GitHub MCP 更适合的场景
- 让 AI 直接读 GitHub 仓库上下文
- 通过工具接口处理 issue、PR、仓库信息
- 让 AI 系统在受控工具边界内访问 GitHub
所以如果你的目标是:
“把我机器里的这个文件夹,变成 GitHub 上一个新的远程仓库,并且推送上去。”
那么最稳的路径仍然是:
- 本地
git - GitHub CLI
gh - 然后再看你是否还需要 GitHub MCP 作为 AI 工作流能力
八、如果把这次经历压缩成一条真正清晰的发布链路
我现在会把“本地文件夹发布到 GitHub”的过程,归纳成下面这条顺序。以后再遇到同样问题,直接按这条链路检查就行。
第一步:确认本地目录是否已经是 Git 仓库
如果不是,就先 git init。
第二步:确认目录里的内容是否已经准备好
如果目录还是空的,或者项目还没有成型,并且你这次的目标本来就不是只发布一个最小仓库,而是发布一个可运行工程,那就先把工程本身补完整。
第三步:完成至少一次本地提交
如果你想推送的是明确的分支内容,通常还是要先有至少一次提交。
第四步:确认 GitHub 认证是否存在
这里最常见的是:
gh auth login- 或者已经存在可用 token / SSH 凭据
第五步:如果 GitHub 上还没有这个仓库,就用 gh 创建
这是 gh 出场的关键时刻。
第六步:配置远端并推送
最后才轮到 git push。
如果前面某一步不成立,最后那条 push 命令大概率就只会把错误信息返回给你。
九、这次经历里,我真正学到的不是命令,而是边界
这整件事看起来像是“AI 帮我执行命令”,但更准确地说,它是一场边界识别。
AI 要想稳定地完成这种任务,不能只会写命令,还必须分清楚:
- 哪些是本地工程问题
- 哪些是 Git 问题
- 哪些是 GitHub 平台问题
- 哪些是认证问题
- 哪些是 MCP 工具接入问题
而从用户视角看,这里面最容易混淆的三个东西就是:
git
管理本地版本历史,负责提交、分支、diff、push/pull。
gh
GitHub 官方 CLI,负责登录 GitHub、创建仓库、处理 GitHub 平台级操作。
GitHub MCP Server
GitHub 官方 MCP Server,负责把 GitHub 能力暴露给 AI 宿主系统调用。
如果把这三者的位置摆正,很多“为什么这里非得装一个东西”“为什么这里不能继续”都会一下子变得清楚。
十、最后给一个最简洁的结论
如果你以后还会对 AI 说:
“把我这个文件夹推到 GitHub 上。”
那你可以直接把内部过程理解成下面这句话:
先把本地目录变成一个合格的 Git 仓库,再确认 GitHub 身份已经打通;如果远端仓库还不存在,在这类场景里可以优先用
gh去创建;如果还想让 AI 以后直接理解和操作 GitHub,再接入 GitHub MCP Server。OpenCode 负责调度 MCP,GitHub MCP 负责暴露 GitHub 能力,而gh在终端工作流里承担了连接 GitHub 平台、创建仓库和处理认证的便捷入口。
这才是“从一句自然语言指令,到真正把一个文件夹发到 GitHub”背后的完整路径。