Git: A Regret Pill for One, a Relay Race for Hundreds of Thousands
第三篇结尾留了一个问题:你辛辛苦苦做出来的东西——让 AI 帮你写的网站、写了一下午的文档——一不小心被自己改坏了,怎么办?
这一篇,就讲那颗后悔药:Git。
一
先看看你的本能会怎么做。
按 Ctrl+Z?撤销只记得最近几步,软件一关就全忘了。所以人的本能是:复制一份。要大改之前,先复制一份。于是每个用过电脑的人,都亲手造过这样的东西:
我的项目
我的项目 - 副本
我的项目 - 最终版
我的项目 - 真最终版
我的项目 - 用这个
我的项目 - 用这个.zip
看着眼熟的话,不用不好意思。但你肯定也体会过它的问题:
- 哪个才是最新的?
- “真最终版”和“用这个”之间,到底改了什么?
- 今天改坏了,想回到三天前的样子——三天前是哪一版来着?
- 换了台电脑,文件夹还在旧电脑里。
把这条路想到底,你真正需要的东西会自己浮出来:
东西会被改坏
↓
所以要能随时回到过去
↓
所以要保存历史的每一版
↓
每一版还得记得"改了什么"
↓
手动复制做不到 → 需要一套自动的存档系统
这个需求太普遍了,早就有人把它做成了工具。它叫:Git。
二
Git 可以简单理解成:给你的文件夹装一套自动存档系统。
被 Git 看管的文件夹,叫仓库(repository)。之后你每次“存档”,Git 都会把当时的样子完整记下来。这个存档动作有个专门的名字:commit(提交)。
整个过程像游戏存档:打 boss 之前存一个,打输了就读档重来。Git 的 commit 就是这个存档,而且比游戏还好用:
- 每次存档,可以附一句话说明这次改了什么(比如“修复了首页打不开的问题”);
- 想知道两档之间差了什么,Git 直接列给你;
- 想回到任何一个存档,一句话的事。
第三篇说过,命令行的思路是“动词 + 对象”。Git 就是往你的词汇表里加几个新动词:
git init:让 Git 开始看管这个文件夹(一个仓库诞生了);git status:现在什么情况?(哪些文件改了、还没存档?)git add .:把当前所有改动装进“待存档”;git commit -m "说明":存档!并附一句说明;git log:列出所有历史存档;git diff:这次的改动,具体动了哪些内容;git restore 文件名:丢弃还没存档的改动,回到上次存档时的样子(读档)。
三
不需要服务器,现在就可以亲手存一次档。先装 Git(官网 git-scm.com 下载,一路下一步;Mac 上第一次使用会提示装一个组件,照做就行)。然后:
mkdir mysite # 建个文件夹
cd mysite # 进去
git init # 让 Git 看管它
echo "我的网页" > index.html # 建个文件,写点内容
git add . # 改动装进待存档
git commit -m "第一版" # 存档!
第一档存好了。现在自己把它改坏:
echo "乱写一气" > index.html # 把文件内容整个覆盖掉
cat index.html # 看看:坏了
git restore index.html # 读档!
cat index.html # 回来了
这一来一回,就是 Git 的全部意义:**你敢改了。**改坏了,一句 git restore 就回去;改到一半想去干别的,git commit 存个档再走。
(注:cat 是“看文件内容”,echo "xxx" > 文件 是“把 xxx 写进文件”——都是第三篇同款思路:动词 + 对象。)
四
到这里,Git 还只在你自己电脑上转。把它接上网络,就到了你在第二篇见过的名字:GitHub。
Git 是工具,GitHub 是网站:把你的仓库传上去存一份。可以粗略理解成“存档的云端网盘”,但比网盘多三样东西:
- 备份:电脑坏了、丢了、换了,仓库还在;
- 同步:本地改完推上去,别处再拉下来,两边永远对得上——还记得第二篇的 SSH 吗?你的服务器上同样是命令行,Git 在那里一样能用;
- 展示:你的仓库就是一个公开的作品柜。以后别人想了解你的水平,第一件事就是看你的 GitHub。
第二篇还说过:GitHub Pages 可以免费托管静态网站。它托管的,正是这样一个仓库——你把网页文件传上去,GitHub 负责让它变成一个能访问的网站。第一篇的请求与响应、第二篇的服务器,到这里全部接上了。
本地和云端之间来回,靠两个动词:git push(把本地存档推上去)、git pull(把云端最新的拉下来)。
五
到这里为止,Git 讲的都是“一个人管好自己的后悔药”。但它还有另一个更出名的身份:协作。
先想一个矛盾:既然每次 commit 都是一份完整存档,那两个人同时改同一个项目,存档不就打架了吗?
Git 的答案叫分支(branch):从某个存档点岔出一条新路线,你在这条路上随便改,不影响主线;改好了,再合并(merge)回去。
主线 ──●───●───●───●───●──→
\ /
●───●───● 你的分支
一个人用时,分支是试验田:想试一个新想法,开条分支去折腾,试砸了整条丢掉,主线毫发无损——你看,这和“后悔药”其实是同一件事的另一面。多人用时,分支就是并行世界:每人一条,最后合并,互不打架。
把这件事放大到全世界,就是开源:一个项目公开放在 GitHub 上,任何人都可以复制一份去改,改好了提交一个申请:“我改的这版,合并进官方版吧?”——这个申请叫 pull request。官方看了觉得好,就合并。全世界最大的协作项目之一——Linux 内核,就是这样被几十万人一点一点改出来的。
顺带一个冷知识:Git 这个工具,当年正是为了管理 Linux 的代码才被造出来的,造它的人就是 Linux 的作者 Linus。所以这个系列到现在形成了一个闭环:服务器上跑的是 Linux(第二篇),你学会了用 Linux(第三篇),而管理代码的 Git 又是 Linux 的亲儿子。
对 vibe coding 的你,这半边意味着什么?GitHub 是全世界最大的代码集散地:你想做的任何东西,大概率有人做过并且开源了,可以直接拿来用、拿来学。你不需要立刻学会合并分支,但要知道:那上面的每个项目,你都有一份“可以随意折腾的副本”的权利。
六
最后说说:AI 时代,这件事为什么变得更重要了。
以前你自己一行行写代码,改坏了什么,心里多少有数。现在 AI 一次能给你改十个文件,你根本看不过来。所以现在的正确姿势是:
让 AI 动手之前 → 先 git commit 存一档
↓
AI 改完了 → git diff 看它到底改了什么
↓
改坏了 → 读档,重来
先存档,再放 AI 出去。这颗后悔药,让你敢让 AI 大胆地改。说到底,Git 在做的事只有一件:把犯错的成本,降到接近零。
七
回头看这一篇:Git 的一半是后悔药,让一个人敢改;另一半是分支和合并,让几十万人能一起写同一个项目。而它的起点,不是“程序员都用 Git”,而是“我会把东西改坏,所以我需要一个存档系统”。这就是想留给你的:
解决问题时,不仅要想怎么成功,还要提前想好:失败了怎么办。
这个思维不挑场景:改文件前先备份、出门前先看返程票、做实验先想对照组——Git 只是把这个本能自动化了而已。下一篇,换一个新问题:两个完全不同的程序之间,怎么互相说话?——API。