正文
如果只是不断保存文件,很快就会遇到问题。昨天的版本还正常,今天修改以后为什么报错?这次到底改了哪几行?别人同时修改了通知格式,怎样把两个人的工作放在一起?
为文件起名“最终版”“最终版二”,能暂时保留几份副本,却难以清楚记录每次变化。版本控制就是用来管理这些变化的。
Git 是一种分布式版本控制系统,能够记录项目的版本历史,帮助我们比较、协作和恢复受管理的内容。 理解它时,可以先把一次提交看作项目在某个时间点的一份可追溯快照。它记录的是被纳入管理的内容,不会自动把文件夹里的所有东西全部打包。
使用 Git,首先需要分清三个位置:工作区、暂存区和本地仓库。
工作区是平时打开、编辑文件的地方。我们在 notice.py 中加入标题检查,首先改变的是工作区文件。暂存区则记录准备放进下一次提交的内容,让我们有机会选择这次究竟保存哪些改动。
提交完成以后,相应的快照进入本地仓库,并关联提交说明、作者等信息。仓库中的历史记录与当前正在编辑的文件,是两个需要分别理解的层次。Git 的快照与三种状态
下面用一组教学命令说明。假设 Git 已安装,我们位于一个专门的练习目录,notice.py 已经存在,提交所需的身份信息也已配置。本篇没有实际执行这些命令。
git init
git status
git add notice.py
git diff --staged
git commit -m "Handle blank meeting titles"
git init 在当前目录初始化仓库;git status 显示文件的跟踪和修改状态;git add notice.py 把这个文件当前的内容纳入暂存区。
git diff --staged 用来查看准备提交的变化。确认以后,git commit 创建本地提交;-m 后面的文字,是这次修改的说明。示例说明表达的是“处理空会议标题”,便于以后回看这次提交想解决什么问题。
这里的“提交”,并不等于把文件发到某个网站。即使没有配置远程仓库,Git 仍然可以在本机保存提交历史。
暂存区也不意味着文件从工作区被搬走。它帮助确定下一次提交所包含的内容。比如,我们先暂存了标题检查,随后又修改了排版,如果没有再次暂存,后加的排版改动就不会因为属于同一个文件而自动进入这次普通提交。
这时,git status 可以同时显示这个文件有已暂存和未暂存的变化。git diff 通常查看已有文件尚未暂存的变化,git diff --staged 则查看已暂存内容相对上次提交的变化。未被跟踪的新文件,也不能只靠一次普通 diff 就完整检查。选择、比较与提交改动
这个区别对实际维护很有用。我们可能同时试过新的通知措辞,但只想先保存修复空标题的部分。通过选择提交内容,就能让一次提交围绕一个清楚的问题,而不必把尚未完成的尝试全部混在一起。
提交说明也应当帮助理解原因。“修改文件”几乎没有提供信息;“空标题时返回明确错误”,则告诉后来的人这次行为发生了什么变化。真正修改了哪些内容,仍然需要看差异,不能只相信说明写得完整。
历史记录还可以帮助找到问题发生的阶段。如果旧版本能够生成通知,新版本却遗漏地点,我们可以比较相关提交,缩小检查范围。但历史中出现一次提交,并不保证它经过测试,也不保证当时的程序符合用户需求。
每次提交都有相应标识,可以用来准确指出讨论的是哪份代码。记录一次测试时,写清对应的提交,比只说“我测过最新版本”更容易复核。这里的提交标识也不是按数字大小排列的版本号,不能靠比较标识大小判断先后。
多人协作时,还会遇到“分支”。
可以先把分支理解为一条有名字的开发历史。我们可以在一条分支上尝试新的通知样式,在检查后把合适的变化合并回来。分支不等于把整个项目手工复制到另一个文件夹;默认在同一工作区切换分支时,显示的文件可能随之改变。
合并也不总能自动完成。两个人修改了同一段通知代码,Git 可能要求处理冲突。解决冲突,需要理解双方修改与最终需求,不能仅凭删除提示标记,就断定合并结果正确。
本地工作清楚以后,再看远程仓库。
远程仓库是另一个可以交换历史记录的仓库,常见情况是位于托管服务或另一台机器。Git 是管理版本的工具,托管平台则可以提供远程存储、权限和协作界面,两者不能直接画等号。
push 会尝试把本地提交等相关对象发送过去,并更新相应远程引用;fetch 取得对方的新历史和引用信息,通常不会直接改写当前工作区;pull 则在取回后,按配置尝试整合到当前分支。整合过程中仍然可能遇到冲突或其他条件限制。本地仓库与远程交换
因此,本地提交成功,不代表远程已经收到;push 成功,也不代表所有未提交文件都已备份。工作区显示干净,同样不能单独证明服务器上的最新变化已经同步到本机。
会议程序里还有一类文件,需要单独安排。例如,运行日志、临时缓存、本机虚拟环境,以及包含账户凭证的配置,通常不应随源代码不加区分地进入仓库。
Git 可以使用 .gitignore 约定哪些未跟踪路径应当被忽略。一个练习项目可能包含这样的规则:
.venv/
__pycache__/
.env
前两项分别示意忽略虚拟环境目录和 Python 缓存目录;.env 则是示例配置文件名。规则的实际范围与放置位置有关,需要按项目检查。不能因为加了这几行,就认为其他名称的凭证文件也会被识别出来。
更关键的是,忽略规则主要作用于尚未跟踪的文件。已经进入版本历史的配置,不会因为后来加入 .gitignore 就从旧提交中消失。忽略也不是加密或访问控制,其他程序仍可能读取本机文件。忽略规则的作用范围
如果凭证已经泄露,需要按实际范围撤销或更换相应凭证,并按协作规则处理相关记录;只从当前文件删掉那一行,不能让已经被复制的内容自动收回。
在 Agent 项目中,代码之外的提示词、工具说明和非敏感配置,也可能需要版本管理。通知生成规则改变以后,开发者需要知道它与哪版工具、哪组测试配合,才能解释行为变化。
不过,Git 保存代码历史,并不能自动撤销程序执行过的所有事情。恢复旧版通知代码,不会让已经发送的通知消失,也不会自动恢复远程日历中的会议。代码版本恢复与业务数据补偿,是不同的问题。
让 Agent 协助修改代码时,也可以使用同样的检查方式:先看它改了哪些文件,再检查准备纳入提交的内容,结合适当测试判断效果。模型说“修改完成”,或者已经创建提交,都不能代替这些证据。
有了版本记录,我们能够更清楚地回答“改过什么”。下一篇会继续解决另一个维护问题:代码相同,为什么在另一台机器上却运行不了?这就需要认识依赖管理与环境隔离。
当前学习编号:02.10 Git 与版本控制。
下一学习编号:02.11 依赖管理与环境隔离。后续还有其他学习编号。
关联分支:版本协同对应 26.09 模型、数据、提示词和工具版本协同、25.15 模型、提示词与配置的发布和回滚;复现与排错对应 24.12 可复现运行与环境快照、24.03 错误分类与根因定位。
修改后的检查对应 02.12 单元测试与集成测试、23.14 回归评测与消融实验;执行后的恢复另见 18.16 可逆操作、补偿与回滚。这些支系会在各自编号中单独展开。