第 1 章

代码提交与版本保存

了解 Git 的工作区、暂存区与提交机制。每当一个功能调试正常,让 AI 及时创建提交保存代码快照,后续改出问题时就能随时安全恢复。

这门课程会学习什么

这门课面向借助 AI Agent 开发网页或软件的初学者。整个流程从保存一个正常运行的功能开始,逐步经历检查代码改动、新建分支尝试新想法、合并代码与解决冲突,再到把项目同步到 GitHub 远程协作与撤销反悔。我们不需要在黑盒终端里手动敲击复杂的命令,而是学会用自然语言把需求准确地告诉 AI Agent,并掌握看懂它返回状态与底层动作的能力。

课程中的所有操作都以自然语言对话为主。我们要学会判断 Agent 改了哪些文件、记录了哪个版本,以及有没有上传到远程。

6 章课程地图同一份改动,从本地存盘走到远程协同。
  1. 存版本第 1–2 章
  2. 管分支第 3–4 章
  3. 协远程第 5–6 章

整门课程分为存版本、管分支与协远程三个阶段。我们将通过一个实际项目,从本地记录第一份代码快照开始,逐步掌握分支管理与多人远程协作。

有了 AI,为什么还需要 Git

借助 AI 编写或修改代码时,我们经常会遇到这样的情况:原本运行正常的登录功能,只是让 AI 调整一下按钮样式,它却在改动样式的同时误改了提交逻辑。此时如果只对 AI 说“改回去”,它未必能准确找回原本的代码。

如果在调整样式之前,我们已经用 Git 记录了正常的版本,就能清楚看到这次修改究竟改变了哪些文件和代码行,并且可以选定已记录的内容来恢复。

Git 是版本管理工具,用来记录和比较项目文件的版本,并在需要时恢复已记录的内容。 一个人做项目也用得上:验证好一个小功能,就留下一个提交;下一次尝试失败时,不必靠记忆让 AI 重写。

平时我们习惯把前后版本叫做 V1、V2,但 Git 并不会自动按这种序号命名,而是用一串唯一的哈希值来标识每次提交,并附带一行修改说明。另外,Git 不会自动保存每一次敲击键盘的编辑;只有执行过提交的文件,之后才能找回。至于数据库里的订单记录、第三方的云端配置等,并不包含在代码快照里。

改动前可以对 Agent 说:“登录功能现在测试能用了。先检查当前改动,帮我把已验证的代码提交保存一下,确认提交完成再去调整样式。”需要恢复时,要明确目标版本和文件范围,第六章会区分几种恢复方式。

Git 和 GitHub 有什么区别

是安装在电脑上的软件。本地查看差异、创建提交和恢复已记录文件,都可以在没有 GitHub 账号、没有网络的情况下完成。安装 Git 也不会自动把项目上传到云端。

GitHub 是云端的代码托管与协作平台。你可以把本地仓库的提交推送到 GitHub;有读取权限的人可以克隆或拉取它,团队还可以围绕分支发起 Pull Request、审查改动。GitHub 上新建仓库也不会自动得到你电脑里的文件。

同一份提交怎样从我的电脑交给同事Git 管理版本,GitHub 托管共享仓库。箭头需要主动同步,不会自动发生。
  1. 我的电脑 · Gitcommit 留在本地仓库;执行 push,才把提交传到下一站。
  2. 云端 · GitHub保存已推送的提交;有读取权限的同事可用 clone 获取仓库。
  3. 同事电脑 · Git得到独立的本地副本;以后按需拉取远程更新,再继续修改。

Git 本身也支持远程协作,GitHub 是常见的托管选择,并非唯一选择。只在本机 commit 后,同事不会自动收到更新;还要完成远程关联、认证和 push,具体操作在第五章。需要回查定义时,见 GitHub 官方的 Git 与 GitHub 说明。

怎样安装 Git,确认它能用

我们可以直接在有本机操作能力的 AI Agent 对话框里说:

“帮我检查这台电脑有没有安装 Git。如果没有,按我的系统完成安装;安装完成后运行 git --version,把版本号告诉我。”

Agent 会在后台检查系统环境并完成配置。我们只需要核对它的回复中是否包含以 git version 开头的版本信息(例如 git version 2.39.5),这就说明当前环境已经能正常找到 Git。

如果 Agent 提示命令未找到,可以让它进一步检查系统的命令搜索路径;普通聊天窗口如果不能直接操作电脑,也可以按 Agent 提供的安装说明完成系统对应的安装程序。安装 Git 与登录 GitHub 是两件事,此时不需要先登录账号。

怎样让当前项目开始使用 Git

Git 安装到电脑后,不会自动对每个文件夹做版本管理。先在编辑器中打开要长期维护的项目根目录,例如项目目录 my-project,确认左侧文件列表里是该项目的源文件。不要在整个桌面或用户目录里初始化。

我们直接对 Agent 这样表达:

“帮我初始化这个项目的 Git。先确认当前目录是否已经是仓库;如果不是才初始化,初始分支用 main。暂时不要提交或推送,完成后告诉我仓库根目录、分支和文件状态。”

了解 Agent 的底层操作:

  • Agent 首先会运行 git status 检查现状;如果已属于仓库,便不会重复初始化。
  • 如果确认不是仓库,Agent 底层会执行 git init -b main。这里的 -b main 指定了初始分支名为 main。
  • 初始化完成后,Agent 会反馈当前状态:显示 On branch main、No commits yet,未被忽略的新文件会列在 Untracked files 下,含义是“仓库已建立,但还没有产生任何提交快照”。
同一个项目:未初始化 → 零提交 → 有版本状态示意,不会读取或修改你的电脑;可用自己的 git status 输出对照。
  1. 未初始化已有网页文件,但没有仓库。status:not a git repository。下一步:git init -b main。
  2. 已初始化 · 0 次提交新增 .git;status:On branch main / No commits yet。接下来检查文件、add,再 commit。
  3. 完成首次提交 · 1 次提交log 中出现哈希与说明。若全部待记录内容已提交且没有其他变化,status 显示 working tree clean。

初始化只为当前项目建立版本管理记录,不改动网页代码,不创建 GitHub 仓库,也不会自动生成第一次提交。如果是通过 clone 下载的已有仓库,通常已经包含这些记录,直接让 Agent 检查状态即可。

初始化后多出来的 .git,里面存了什么

按上面的初始化方式,项目根目录会多一个隐藏的 .git 文件夹。在编辑器或系统文件管理器中开启“显示隐藏文件”就能看到它。它不只是配置文件夹,还保存了本项目的全部版本管理数据与快照历史。

同一项目里,网页文件与 .git 分别存什么两侧都在你的电脑上;右侧由 Git 维护,不是 GitHub 云端。
my-project 中的网页源文件你和 AI 日常查看、修改的内容
  • src/components/LoginForm.tsx:当前登录表单
  • src/styles.css:当前样式
  • 普通保存更新这些文件,不会自动生成提交
my-project/.git 中的管理数据Git 用来记录版本、暂存内容和当前位置
  • objects:文件内容、目录快照与提交对象
  • refs / HEAD:分支记录与当前检出位置
  • index:暂存区记录
  • config / logs:仓库设置与引用移动记录

图中列的是常见存储位置:objects 保存文件内容、目录快照和提交记录等对象;refs 记录分支等引用,HEAD 标明当前检出位置;index 保存暂存区记录,config 保存本仓库设置,logs 可记录引用的移动。它们随操作逐步产生,刚 init 时并不一定全部存在,也还没有任何已提交版本。

我们日常编写和修改的是网页源文件,.git 目录则由 Git 命令自动维护。千万不要把它当作临时缓存删掉:只保存在本机、尚未推送到远程的历史记录都会因此丢失。在第六章介绍的独立工作目录中,.git 也可能是一个指向实际存储位置的引用文件。平时我们只需要知道它负责存盘,不需要手动修改其内部文件。

第一次提交前,怎样设置作者身份

在第一次创建提交之前,我们还需要完成一项基础设置:作者身份配置(git config)。许多初学者在第一次尝试保存版本时,终端会弹出一行拦截提示:Author identity unknown: Please tell me who you are。这是因为 Git 的每一份提交快照都必须明确记录责任人。如果此前从未设置过身份,Git 就不知道在提交记录中该署上谁的名字。

你可以直接对 Agent 说:

“帮我配置一下当前项目的 Git 提交身份,名字用‘你的名字’,邮箱用‘你的邮箱@example.com’。配置完成后查询一下确认结果。”

Agent 底层会执行对应的设置命令:

  • 设置作者名字:git config user.name "你的名字"
  • 设置作者邮箱:git config user.email "你的邮箱@example.com"

完成后 Agent 会通过查询命令核对结果。如果希望它们成为所有项目的默认配置,可以告诉 Agent 加上全局设置(--global)。这里设置的是提交的作者签名,不是 GitHub 登录密码。

文件在 Git 里的四个区域

在借助 AI 编写项目时,我们通常会打开一个像 Cursor、VS Code 或 Windsurf 这样的软件,这类软件被称为代码编辑器。编辑器的界面一般包含三个主要部分:左侧是项目文件列表,展示当前目录包含哪些文件;中间是代码编辑窗口,像记事本一样展示并修改具体文件的内容;侧边则是我们与 AI Agent 对话的窗口。

当我们让 AI 生成代码,或者自己手动修改了几行内容后,按快捷键(Ctrl+S 或 Cmd+S)保存文件,改动只是写进了电脑硬盘上的普通文件里,这就像在文档软件里保存了一次修改。很多初学者的误区在于,以为文件保存了,Git 就自动记录了历史。事实并非如此:普通的保存操作只是覆盖了本地磁盘上的上一版文字;如果不经过 Git 的专门记录,Git 就不能据此恢复刚才的状态;编辑器自己的本地历史或备份是另外的机制。

日常文件保存 vs Git 提交快照普通保存只修改当前磁盘文件;Git 提交才会在历史库中生成可恢复的快照。
日常文件保存(Ctrl+S / Cmd+S)只更新电脑硬盘上的当前物理文件
  • 文件内容直接被最新一次编辑覆盖
  • 如果 AI 误改原有逻辑,上一版内容直接丢失
  • 没有版本编号,不能回到历史状态
Git 暂存与提交(add + commit)在 .git 历史库中建立永久存档
  • git add:挑选改好的文件,登记到待提交清单
  • git commit:生成带有唯一哈希值的版本快照
  • 后续即使代码改乱,也能随时按编号完整找回

把日常保存与 Git 记录区分开来,我们可以把它们看作两道分工明确的工序:日常保存只负责更新当前磁盘文件,随时可能被下一次编辑覆盖;而 Git 的记录流程则是在这之上建立一套独立的存档系统。

在 的运行机制中,文件主要在四个区域之间流动:

第一是工作区(Working Tree)。在物理层面,工作区就是我们电脑硬盘上的真实项目文件夹(例如桌面上建好的项目目录)。我们在编辑器左侧文件列表看到的、在中间窗口正在阅读和修改的,以及在电脑文件管理器里能点开的项目文件,都在这里;隐藏的 .git 则保存 Git 的管理数据。这里就像我们的日常工作台,我们和 AI 可以随时修改或测试代码。

第二是暂存区(Staging Area / Index)。它记录准备进入下一次提交的文件内容,相当于一份待提交的清单。执行 git add 时,Git 保存的是文件当时的内容,而不只是勾选文件名。例如登录按钮先写成“登录”,add 后又改成“登录中”,普通 git commit 记录的仍是“登录”。想提交后来的文字,需要再次 add;同一个文件也可以只有部分改动进入暂存区。

第三是本地仓库(Local Repository)。本地仓库保存本机已经记录的项目版本。当我们在项目根目录初始化 Git 时,电脑中会生成一个隐藏的 .git 文件夹,本地仓库就存放在这里。确认暂存内容正确后,执行 git commit,Git 就会按暂存区记录生成项目快照,并保存修改说明。只要对应提交还在仓库中,就能恢复那次记录的文件内容;这不包含未提交的后续编辑。

第四是远程仓库(Remote Repository)。远程仓库是放在另一台机器上的仓库,例如托管在 GitHub 上的项目仓库。通过推送操作(git push),我们把本地仓库里的提交记录上传到云端。推送成功的提交可以从远程取回,团队成员也能据此同步进度;仅存在本机、尚未推送的提交不在这份远程副本里。

同一份改动怎样走过四个区域工作区里的修改还不是历史;add 记录当时的内容,commit 按暂存区生成快照。
src/components/LoginForm.tsx+ 本地修改
工作区add
add 时的内容src/components/LoginForm.tsx
暂存区commit
c7d8e9fsrc/components/LoginForm.tsx
本地仓库push
origin 上的 mainc7d8e9f
远程仓库

无论是敲击命令行(例如 git add 和 git commit),还是在编辑器的图形界面上点击按钮,或者直接对 AI Agent 说一句话让它处理,底层都是在推动文件在这四个区域之间流转。理清了四个区域的分工,我们就能清楚知道改动目前停留在哪一步,知道恢复时有哪些已记录的版本可用。

提交不是文件拷贝,而是一棵快照树

很多初学者在没有接触版本控制前,习惯用复制文件夹的方式做备份,例如给目录命名为“项目最终版”、“项目最终版2”。这种做法不仅占用大量磁盘空间,而且无法看清两次修改之间到底改了哪几行代码。

的机制与手动复制完全不同。每次普通提交,Git 都会根据暂存区记录生成整个已纳入版本管理的文件树快照;未跟踪、被忽略或尚未暂存的新改动不会自动进入它。如果某个文件在这次提交中没有被修改,Git 不会重复保存该文件,而是直接引用上一次的记录;如果文件被修改了,Git 则记录修改后的新对象。

平时我们习惯按 V1、V2 称呼前后版本,但在团队多人协作或分支同时推进时,单纯靠序号很容易发生重名混乱。Git 对提交对象计算 ,为每一次提交生成一个全局唯一的标识码;c7d8e9f 这样的短值是便于阅读的缩写。提交对象记录文件树、作者、说明、时间和父提交引用(可理解为 )。所以即使文件内容相同,作者、时间或父提交改变,也可能得到不同的提交哈希。普通提交有一个父提交,首个提交没有,后面会看到拥有两个父提交的合并。

Git 提交历史链条与快照模型每次提交引用已记录的完整文件树。下方文件名只列本次改动,箭头指向父提交;哈希为示意值。
C0
0f1e2d3
chore: 初始化项目结构
README.md .gitignore
C1
a1b2c3d
feat: 完成首页基础布局
index.html src/styles.css
C2
c7d8e9fmainHEAD ➔
feat: 完成登录表单与字段验证
src/components/LoginForm.tsx src/lib/validation.ts

每个提交引用一份已记录的文件树。文件名仅列本次改动,反向箭头指向父提交。

做一次可以核对的提交

下面以项目中刚刚在浏览器里验证通过的登录功能为例。功能测试正常后,我们不需要自己去翻找具体改动了哪几个代码文件,更不需要手动编写技术提交说明,直接用自然的口语对 Agent 提出提交要求即可:

“刚才测试登录功能没问题了。帮我把这次登录功能的改动提交一下,不要混入未完成的临时文件。提交说明你根据改动帮我起一个简明的就行,提交完成后告诉我改了哪些文件。”

了解 Agent 在底层为我们完成的步骤:

  • 首先检查分支状态与现有改动(对应 git status),找出与登录功能相关的改动文件(如 LoginForm.tsx 与 validation.ts),排查是否存在未完成的临时文件。
  • 审查登录功能文件的改动范围(对应 git diff)。
  • 将目标文件当前的内容登记到暂存区(对应 git add)。
  • 再次核对暂存清单(对应 git diff --cached),确认准备提交的内容准确无误。
  • 根据改动自动生成规范的提交说明(例如 feat: 完成登录表单与字段验证),生成提交快照(对应 git commit -m)。
  • 最后向我们汇报提交完成并列出改动的文件列表。

判断一下:add 后又改了按钮文字,但没有再次 add,这次 commit 会记录哪版? 是 add 时的文字。新的编辑还留在工作区,不会因为文件名已被选中就自动提交。

常见任务怎样向 Agent 表达

我们不需要死记硬背具体的参数命令。在借助 AI 开发时,清楚说明业务意图和范围即可,同时了解底层命令能帮我们看懂 Agent 的操作:

  • 想了解当前仓库情况:对 Agent 说“查看当前分支和文件状态,并列出最近五次提交说明”(底层对应 git status 与 git log -5 --oneline)。
  • 想审查 AI 改动了什么:对 Agent 说“检查这次未暂存和已暂存的代码差异,告诉我改了哪些行”(底层对应 git diff 与 git diff --cached,第二章展开)。
  • 想尝试新功能:对 Agent 说“基于当前的 main 分支新建 feature/cart 分支并切换过去”(底层对应 git switch -c,第三章展开)。
  • 想合并或同步代码:对 Agent 明确指定要合并的分支名称,或要求拉取远程更新(第四、五章展开)。
  • 想撤销或暂停工作:对 Agent 准确说出要放弃或保留的文件范围(第六章展开)。

commit 是本地记录,push 才是向远程发送提交;日常保存文件不等于这两步中的任何一步。

怎样向 AI Agent 描述提交需求

借助 AI 写代码时,我们通常不清楚底层具体改动了哪几个代码文件,更不需要自己去苦思冥想规范的提交说明,这些工作 AI 都能自动处理。

但如果我们只对 AI 简单说一句“帮我提交一下代码”,AI 可能会把调试时产生的临时日志、未完成的代码甚至本地配置文件一起提交上去。

因此,向 AI 提出提交要求时,最自然也最稳妥的方式是把重心放在业务功能和边界约束上:

  • 说明刚测完的功能:告诉 AI 哪个功能在界面上已经验证通过,只提交该功能相关的改动;
  • 提醒隔离无关文件:明确要求 AI 检查工作区,不要混入未完成的临时文件或调试日志;
  • 让 AI 自动生成说明并汇报:让 AI 根据改动内容自动拟定一句简明的提交说明,并在提交完成后告知具体修改了哪些文件。
向 AI Agent 发出规范提交指令示例对话:用自然语言说明已验证的功能,让 AI 自动挑选文件、生成说明并汇报结果。

刚才测试登录功能没问题了。帮我把这次登录功能的改动提交一下,不要混入未完成的临时文件。提交说明你根据改动帮我起一个简明的就行,提交完成后告诉我改了哪些文件。

示例结果:已完成提交,说明为「feat: 完成登录表单与字段验证」。本次提交包含 2 个改动文件(LoginForm.tsx 和 validation.ts);工作区中未完成的 debug.log 已保留未提交。

对话中的回复只是格式示例。实际验收要看已提交的差异和剩余文件状态,不能只看 Agent 说“已完成”。

本章总结:理解区域流转,规范存盘要求

在这一章中,我们梳理了 Git 中文件的四个区域,明确了提交快照的数据结构,并掌握了如何向 AI 描述提交需求。在本地验证通过一个独立的小功能后,及时让 AI 创建一个说明完整的 Commit,是保证项目能够随时恢复到稳定状态的基础。在下一章中,我们会学习如何使用 Diff 检查 AI 修改的代码,并通过忽略规则过滤不需要的文件。

本章目录