提交循环


假设你在 weather-app 项目上已经忙活了二十分钟。你修复了 src/index.js 里的一个真实 bug(温度换算算错了),顺手又开始重新调整 styles.css 的样式,但这部分改动还没写完,也还不想让别人看到。你现在想把这个 bug 修复保存成一个独立的检查点,而不想把没写完的样式改动也一起带上。
这正是提交循环要解决的问题。如果你还没有建好仓库,可以先看 你的第一个仓库,那里讲了 git init 和克隆仓库的方法。从这里开始,本章假设你已经有一个打开的仓库了。
三个环节:工作目录、暂存区、提交
在 Git 里,你做的每一处修改都要经过三个环节才能变成永久的历史记录。工作目录就是项目现在在磁盘上的样子,也就是你正在编辑的那些文件。**暂存区**是一个中转地带,你把接下来想要保存的那些改动放在这里。提交则是保存下来的快照本身——一旦你写下它,连同描述它的提交信息一起,就成了提交。
想象一下搬家打包的场景。你的整个房子就是工作目录:你拥有的一切东西,不管现在是什么状态。你已经打包好、贴上封条放在门口的箱子就是暂存区:只包含你特意选中要带走的东西。载着这些箱子开走的搬家卡车就是提交:记录了那一刻究竟带走了什么,外面还贴着标签写明里面是什么。
来看看这套心理模型在真实终端里的样子。编辑完 weather-app 里的两个文件后,git status 只是读取当前状态,不会改动任何东西:
$ git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: src/index.js
modified: styles.css
no changes added to commit (use "git add" to commit)两个文件都显示为"未暂存",因为仅仅编辑文件只会改变你的工作目录。在你用 git add(下一节会讲)告诉 Git 之前,不会有任何东西进入暂存区。
正是在这里,暂存区存在的意义才真正体现出来。暂存区让你可以精确选择哪些内容进入提交,不受工作目录里还有哪些其他改动的影响。如果没有暂存区,保存一个检查点就得把磁盘上的所有改动一次性都带上,不管是否准备好。
有了暂存区,你就可以把 src/index.js 里已经完成的 bug 修复暂存起来,把还没写完的 styles.css 留在外面,只提交真正完成的那一部分。暂存区和工作目录可以同时保存不同的内容——这一点几乎每个人在第一周都会被绊一下。一旦你想通了这一点,Git 日常工作流的其他部分就都顺理成章了。
git add 来选择哪些内容进入暂存区,这正是你能保存一个已完成的改动、同时留下一个未完成改动的原因。 暂存改动:git add
git add 把一处改动从工作目录移入暂存区。指定你想放进下一次提交的那个文件:
$ git add src/index.js
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: src/index.js
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: styles.csssrc/index.js 已经移到了"Changes to be committed"(待提交的改动)下面,bug 修复已经暂存好,随时可以提交。styles.css 还列在"未暂存"下面,正好符合你的心意——毕竟样式还没改完。再运行一次 git add styles.css 也会把它暂存进去;而运行 git add . 会把当前文件夹里所有改动过的文件一次性全部暂存,等你确认磁盘上的一切都真的准备好了,这样用起来会很方便。
git add <file> 把该文件当前的改动移入暂存区,为下一次提交做好准备。还没 add 的文件会留在外面,所以你可以完成一件事,同时留另一件事半途暂放。git add . 会一次性暂存所有改动过的文件,等一切真的准备好了用起来很方便。 保存一份快照:git commit
一旦暂存区里放好了你想要的内容,git commit 就能把它保存成一份永久快照,-m 参数("message" 的缩写)用来提供随之保存的描述文字:
$ git commit -m "Fix temperature conversion in Celsius-to-Fahrenheit formula"
[main 4f2a1c9] Fix temperature conversion in Celsius-to-Fahrenheit formula
1 file changed, 1 insertion(+), 1 deletion(-)只有 src/index.js 被提交进去了,因为你只暂存了这一个文件。styles.css 依然停留在工作目录里,处于已编辑但未提交的状态,等着你把样式改完再说。那个短 id,4f2a1c9,就是这次提交的标识,历史记录 一章会讲怎么查看项目完整的提交列表。
git commit -m "message" 会把当前暂存区里的内容保存成一份永久快照,并附上你给的提交信息。没有暂存的内容会留在外面,仍然可以继续编辑。提交信息要简短清楚地说明这次提交做了什么,未来的你回头看的次数会比你想象的多得多。 
