讲解

Git 管理的文件在三个区域之间流动:工作区(你实际编辑的文件)、暂存区(index,也叫 stage)和仓库(提交历史)。工作区里改完文件,先 git add 把改动放进暂存区,再 git commit 把暂存区的内容提交进仓库。为什么要多一个暂存区?因为它让你精确控制每次提交包含什么:改了五个文件,可以把其中两个相关的改动 add 后提交,另外三个留到下一次——每次提交都是一件完整、独立的事。

git status 是看清当前局面的命令,也是使用频率最高的 Git 命令。它把文件分成几类:Untracked(新文件,Git 还没跟踪)、Modified(已跟踪文件被修改但还没暂存)、Staged(已暂存、等待提交)。同一个文件可能既有已暂存的改动又有未暂存的新改动,status 会分别列出。git status --short(或 -s)用紧凑的两列字母显示状态:M 表示修改、A 表示新增、?? 表示未跟踪,第一列是暂存区状态,第二列是工作区状态。

git add 后面跟文件路径:git add app.js 暂存单个文件,git add . 暂存当前目录下所有改动,git add -A 暂存整个仓库的所有改动。还有一个交互式的 git add -p,逐块(hunk)询问你是否暂存,适合把一个大改动拆成几个逻辑提交。add 错了不要紧——暂存只是中间状态,后面的 restore 一章会讲怎么撤出来。

示例

在演示仓库里制造一些改动,观察三个区域之间的流动:

echo "新功能代码" > feature.txt
echo "一行修改" >> app.js
git status
git status --short
git add feature.txt
git status --short
git add app.js
git status --short

第一次 git status --short 会显示 M app.js(已修改未暂存)和 ?? feature.txt(未跟踪);暂存 feature.txt 后它变成 A;全部暂存后两个文件都进入第一列,等待提交。

常见坑

  • 提交后才发现漏了文件:commit 只包含暂存区内容,没 add 的改动不会进提交。养成 commit 前 git status 看一眼的习惯。
  • git add . 把不该提交的东西加进去:日志、临时文件、密钥一旦提交进历史,删除也需要额外操作。先用 .gitignore 排除(后面专门一章),add 前后都用 status 确认。
  • 以为 add 是一次性的:add 之后又改了文件,新改动需要再次 add 才会进入暂存区,否则提交的是 add 那一刻的内容。
  • 对未跟踪文件用 git commit -a:commit 的 -a 选项只会自动暂存「已跟踪」文件的修改,新文件仍然必须先 add。

小结

改动沿「工作区 → 暂存区 → 仓库」流动,git add 负责中间这一步,git status 随时告诉你每个文件在哪。暂存区让每次提交的内容可控。下一节把暂存的内容正式提交进历史。