← 学习路线

Git:存档、回退与不该提交的东西

怎样用 Git 给 AI 的改动留好退路?哪些东西一旦提交进去,就很难再拿出来?

课型:流程·约 20 分钟·5 个术语

先看出事的那一刻

2026 年 8 月 19 日,一份学习资料要放进 Git 仓库。AI 执行了最常见的两条命令,git init 和 git add -A。屏幕上列出了 124 个要提交的文件,它看了前 5 行,提交,推送。

推送卡住了。重试,又卡住;第三次,一直停在"计数对象"这一步。查一下仓库里每个文件的大小,排在最前面的是一个 516MB 的语料压缩包:忽略规则只排除了 PDF 和 Word,没管压缩包。

这不是这两个项目唯一一次把不该提交的东西放进仓库。另一个仓库里,两个数据库日志文件一待就是两个月:

这节课要回答的是:怎样用 Git 给 AI 的改动留好退路?哪些东西一旦提交进去,就很难再拿出来?

装备几个词

为什么要懂

AI 替你做了

AI 会替你执行 git add、git commit、git push,一条命令就把所有改动存档、上传。

留给你的

看一眼到底提交了什么:哪些文件不该进仓库、这次提交是不是只做了一件事。git add -A 不会替你挑。

不懂的代价

大文件让推送卡死、仓库膨胀;数据库文件和密钥进了历史,删掉当前版本,历史里也还留着,很难清理干净。

存档、分支、退路

和 AI 一起改代码,最实用的 Git 习惯只有三个:

  1. 动手之前先提交一次,让工作区是干净的。改坏了,git restore . 就能回到这一刻。
  2. 每完成一件独立的事就提交一次。出了问题能精确找到是哪一次,用 git revert 提交号 只撤回那一次,不用整个推倒重来。
  3. 大改动放在分支上做。这个网站的每个阶段都在单独的分支上,推送后先看预览地址,确认了才合并到 main 上线。

这三件事的共同点,是给每一步留一个存档。AI 改得越快、越多,存档就越要密。

哪些东西不该进仓库

类别例子为什么
依赖node_modules体积巨大,随时能按锁文件重新装
构建产物dist每次构建重新生成
密钥和本地配置.env进了历史就要当作已经泄露(第 11 课)
数据库文件*.db,以及旁边的 -wal、-shm带着用户数据,而且随时在变
大文件压缩包、视频、原始语料让仓库膨胀、推送变慢,应该放到别处

.gitignore 就是这张清单的执行者。它有两个特点要记住:

  • 规则写窄了,就会漏。data/*.db 只匹配 academy.db 本身,SQLite 在旁边生成的 academy.db-wal 和 academy.db-shm 一个都没挡住。
  • 它只管还没提交过的文件。第二天规则补成了整个 data/ 目录,可这两个文件已经在仓库里,Git 照样继续跟踪。
深潜文件已经提交了,怎么移出去+
git ls-files data/                     # 仓库里到底跟踪着这个目录下的哪些文件
git rm --cached data/academy.db-wal    # 移出仓库,但保留本地文件
git commit -m "chore: 数据库文件移出仓库"

这样之后的提交就不再包含它了。但历史里的旧版本还在,任何能访问仓库的人都能翻出来。要彻底清除,得改写全部历史再强制推送,代价很大,要不要做,取决于数据有多敏感。

E2E Review 最后选了彻底清除:先把整个仓库打包备份,再改写全部 56 个提交,把两个文件从每一个提交里删掉,然后强制推送。

第一次改写就出了岔子。这次用的是 Git 自带的 git filter-branch,命令里顺手加了 --prune-empty,想删掉"删完文件后变空"的提交;它却把一个原本就是空的检查点提交也一起删了。改写完核对提交数,56 个变成了 55 个;把新旧提交逐个配对,才找出少的是哪一个。去掉这个参数、从备份重做,56 个一个不少。

所以改写历史之后要核对两件事:该删的删干净了没有,别的是不是原样。另外,强制推送之后,GitHub 上按旧的提交号仍然能打开旧提交:平台那边的副本,要另外请平台清理。

深潜推送之前看一眼+

学习资料库那次,只要在提交前多跑一条命令,就能看到那个压缩包:

git ls-files -z | xargs -0 du -h | sort -rh | head

它按大小列出仓库里的文件,516MB 的压缩包会排在第一行。修法也很简单:把 *.zip 加进忽略规则,把压缩包移出这一次提交,再推送。前后只用了十秒,大文件从没到过 GitHub。

找茬

下面是两个仓库的真实忽略规则和命令(节选)。一个仓库用 SQLite 数据库,开着日志模式;另一个仓库的资料目录里有一个 516MB 的压缩包。找出让不该提交的东西溜进仓库的地方。

这段 gitignore / Shell 里埋了 5 处问题。点击你觉得有问题的行,至少找出 3 处再揭晓。

查看代码与答案(5 处问题)
 1  # E2E Review 的 .gitignore(2026-07-26,节选)
 2  *.log
 3  .DS_Store
 4  data/*.db
 5  
 6  # 同一次提交里新增的文件(git show --stat,节选)
 7   data/academy.db-wal | Bin 0 -> 135992 bytes
 8  
 9  # 学习资料库的 .gitignore(2026-08-19)
10  .DS_Store
11  *.pdf
12  *.xlsx
13  *.docx
14  *.pptx
15  
16  # 第一次提交之前
17  git init -q && git add -A
18  git status --short | head -5
  • 第 4 行 · 中危 · 规则写得太窄:data/*.db 只匹配 academy.db 本身。SQLite 在日志模式下会在旁边生成 -wal 和 -shm 两个文件,这条规则一个都挡不住。 该问的话:这个目录下会生成哪些文件?这条规则能覆盖全部吗?
  • 第 7 行 · 高危 · 数据库日志进了提交:Bin 说明这是一个二进制文件。它是数据库的日志,里面有账号数据;混在一次功能提交里,没人注意到,就这样在仓库里待了两个月。 该问的话:这次提交里有没有二进制文件?它们是什么,该不该进仓库?
  • 第 14 行 · 中危 · 清单到这里就结束了:排除了 PDF 和 Office 文档,却没想到压缩包。忽略规则最好按"不该进仓库的类别"来写,而不是按"眼下想到的几种格式"。 该问的话:这个目录里有哪些大文件?它们的格式都被忽略规则覆盖了吗?
  • 第 17 行 · 中危 · 把所有东西一起加了进来:git add -A 会把目录里所有没被忽略的文件都加进暂存区。忽略规则一有漏洞,漏网的东西就全进来了。 该问的话:这次加进来的文件里,有没有不该提交的?
  • 第 18 行 · 高危 · 124 行只看了前 5 行:head -5 只显示了前 5 个文件,516MB 的压缩包藏在剩下的 119 行里。检查只做了一半,等于没做。 该问的话:这次要提交的完整文件清单是什么?其中最大的几个文件是哪些?

快测

1. 你在 .gitignore 里加上了 .env,可 git status 显示它还在被跟踪。为什么?

查看选项与答案
  • A. 这个文件之前已经提交过,忽略规则管不到已跟踪的文件(正确)——要用 git rm --cached 把它移出仓库;它要是含有密钥,还得去作废那些密钥。
  • B. 规则要等你重新克隆一次仓库,才会重新生效——规则要重新克隆之后才生效。可重新克隆下来,这个文件照样在仓库里,因为它已经在历史里了。
  • C. 规则没匹配上,得写成 *.env 才会生效——规则没写对,换个写法就行。可 .env 已经能匹配到这个文件,问题不在写法:它之前已经被提交过,忽略规则管不到已跟踪的文件。

.gitignore 只能挡住还没进来的,挡不住已经在里面的。

2. AI 一口气改了 30 个文件,其中一处改坏了。怎样最容易只撤回那一处?

查看选项与答案
  • A. 把 30 个文件放进同一个提交,出问题时撤回这个提交——反正能撤回提交,一个提交就够了。可撤回一个提交,撤回的是整个提交,30 个文件的改动会一起被撤掉;要只撤回那一处,得先把改动按目的拆成独立的提交。
  • B. 改动按目的分开提交,git revert 出问题的那个(正确)——提交拆得越细,撤回得越精确。出了问题能找到是哪一次,用 git revert 提交号 只撤回那一次。
  • C. 用 git restore . 回到改动之前,再让 AI 重做——整个退回去,再让 AI 重做最干净。可 git restore . 会把 30 个文件全部退回上一次提交,好的改动也一起丢了,等于整个推倒重来。

小而独立的提交,就是最好的退路。

3. 第一次推送一直卡住不动。最先该检查什么?

查看选项与答案
  • A. 先换成图形界面的 Git 客户端再推一次——换个客户端也许就顺了。可换工具不会让 516MB 变小;卡住的是要推送的内容,不是客户端。
  • B. 先看这次提交里有没有体积很大的文件(正确)——按大小列出仓库里的文件,一眼就能看到:git ls-files -z | xargs -0 du -h | sort -rh | head。
  • C. 先排查网络,换个网络或代理再重新推送一次——推送慢,多半是网络问题。网络是可能的原因,但先看要推送的东西有多大:大文件是最常见的元凶。

推送慢,先看体积。

判断时刻

你发现仓库里提交着两个数据库日志文件,里面可能有账号数据。仓库是私有的。AI 给了三个方案。

你会选哪一个?

三个选项各自的代价
  • A. 在 .gitignore 里加上规则——考察看起来修好了:最省事,也最没用:忽略规则管不到已经提交的文件。这个项目当时就是这么做的,结果文件又在仓库里待了两个月。
  • B. 用 git rm --cached 移出仓库,确认忽略规则覆盖它们——考察止住,但历史还在:从下一个提交起不再跟踪,本地文件也保留着。但历史里的旧版本还在,能访问仓库的人都能翻出来;数据要是敏感,这一步还不够。
  • C. 移出仓库之后,再改写历史,把它们从所有提交里抹掉——考察彻底,但有代价:最彻底,但要改写全部提交、强制推送,所有协作者都得重新拉取,操作不慎还会丢提交。值不值得,取决于数据有多敏感、仓库有多少人能看到。E2E Review 最后选的就是这条,第一次改写真的少了一个提交,是核对提交数才发现的。

提交之前拦住,比提交之后清理便宜得多。把忽略规则写宽一点、每次提交前完整看一遍 git status,是最划算的两个习惯。

带走

下次让 AI 做这件事时,问它

  1. 开始改动之前,工作区是干净的吗?请先提交一次当前状态。
  2. 这次要提交哪些文件?有没有依赖目录、构建产物、密钥、数据库文件或大文件混在里面?
  3. 把这次的改动按独立的目的拆成几个提交,每个都能单独构建通过。
  4. .gitignore 覆盖了哪些类别?仓库里有没有已经被跟踪、却本不该提交的文件?

自己验证

  • git status --short:提交之前完整看一遍,不要只看前几行。
  • git ls-files -z | xargs -0 du -h | sort -rh | head:找出仓库里最大的几个文件。
  • git ls-files data/:看某个目录下到底跟踪着哪些文件。

提交之前看一眼,比提交之后清理便宜得多。