把一个本地文件夹发布到 GitHub,中间到底发生了什么?

从 git、gh 到 GitHub MCP,再到 OpenCode 的一次完整拆解

Posted by Hux on March 29, 2026

这篇文章想回答的不是“怎么 push 一次代码”,而是“当我对 AI 说,把这个文件夹发到我的 GitHub 上吧,它中间到底经历了什么,又为什么会卡住,最后为什么还得用 gh?”

前几天我给 AI 下了一个看起来很简单的指令:把 D:\Github\MyPet 这个文件夹推到我的 GitHub 仓库区里,顺便还要安装一下 github-mcp-server

表面上看,这像是一个“执行几条命令”的问题。但真正走下来我才发现,这里面至少同时涉及了四层能力:

  1. 本地文件系统和项目状态
  2. 本地 Git 仓库管理
  3. GitHub 平台上的远程仓库创建与认证
  4. AI 工具如何通过 MCP 访问 GitHub 能力

如果不把这四层分开,几乎一定会把 gitgh、GitHub MCP Server 以及 OpenCode 之间的关系混成一团。本文就按一次真实执行链路,把这件事拆开讲清楚。


一、从一句“帮我推到 GitHub”开始,系统到底先做了什么

当我发出“把这个文件夹推到 GitHub”这种指令时,AI 通常不会立刻就执行 git push。在这次场景里,更稳妥的做法是先做一轮上下文确认。

这一步通常会先回答几个问题:

  • 目标文件夹是不是一个现成的项目?
  • 它是不是已经是一个 Git 仓库?
  • 远程仓库是否已经存在?
  • 本机是否已经具备 GitHub 身份认证?
  • 用户说的“安装 github-mcp-server”,到底是装成什么形态?

也就是说,系统先要判断:这是一个“已有仓库的推送问题”,还是一个“从零建仓并发布”的问题。

在我这次的实际过程里,第一轮检查得到的结论是:

  • D:\Github\MyPet 一开始并不是一个现成的 Git 仓库
  • 目录最初也不是一个完整的前端工程,我还先在里面初始化了一个 React 项目
  • 本机当时没有安装 gh
  • 也没有现成可用的 GitHub 登录态可以直接完成仓库创建

这就决定了后续的动作不适合直接进入 push,而是要先补全前置条件。


二、真正的第一步不是 push,而是把文件夹变成一个“可发布对象”

很多人会把“推到 GitHub”理解成一个单动作,但实际上它至少包含两段:

  1. 先把本地目录整理成一个 Git 仓库
  2. 再把这个 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 到底是什么

ghGitHub 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,而是认证

这一轮执行里最有代表性的地方,不是某条命令本身,而是中间发生的“卡住”。

系统当时做了这些事情:

  1. 安装了 GitHub CLI
  2. 初始化了本地仓库
  3. 完成了本地提交
  4. 准备创建远程仓库并推送

然后在这一步停住了。

原因非常明确:

  • 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)交互流程到底是什么样

如果把这条链路写成步骤,大概是这样:

  1. OpenCode 启动
  2. 读取 MCP 配置
  3. 连接 GitHub MCP Server(本地或远程)
  4. 获取该 server 提供的 tools/resources/prompts
  5. 当模型在对话里需要 GitHub 能力时,OpenCode 发起 MCP 调用
  6. 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 上一个新的远程仓库,并且推送上去。”

那么最稳的路径仍然是:

  1. 本地 git
  2. GitHub CLI gh
  3. 然后再看你是否还需要 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”背后的完整路径。