摘要:上一篇文章我们成功安装了 Git,并运行了 git init。但你一定很困惑:文件改了,怎么保存?保存了,怎么找回来?本篇将为你揭开 Git 最核心的三个区域——工作区、暂存区和版本库的神秘面纱。我们用“购物车”的类比让你秒懂暂存区的意义,再通过大量实操带你掌握 git add、git commit、git status、git log、git diff、git reset、git checkout — 等命令,并附带撤销错误操作的救命锦囊。读完这篇,你将真正拥有代码的“时光穿梭”能力。
一、工作区、暂存区、版本库
很多教程一上来就让你 git add、git commit,但若不理解 Git 的“三区模型”,后面一切操作都是死记硬背。
想象一下你要搬家,从旧房子(工作区)把东西打包成纸箱(暂存区),然后装车运到新家(版本库)。这个比喻非常接近 Git 的逻辑:
-
工作区(Working Directory):你电脑里能看到的项目文件夹,你在里面增删改文件,就像在旧房子里收拾东西。
-
暂存区(Staging Area / Index):一个临时存放修改的清单,它记录了“我打算在下次提交中包含哪些改动”。相当于你打包好的纸箱,可以随时增减物品。
-
版本库(Repository):.git 目录,永久存储所有提交的快照和历史。相当于最终搬入的新家,所有东西都归档妥善保管。
为什么要有暂存区?为什么不一步到位直接提交?这是因为在真实开发中,你可能一次改了 5 个文件,但其中 3 个是完成的功能,另外 2 个还在调试。暂存区允许你精细地控制每一次提交的内容,保持提交记录的清晰和原子性。
二、文件流转:从创建到成为历史
接着上一篇文章建立的 my-first-git 仓库。我们现在有一个 readme.txt 文件,用 git status 查看:

这里的 Untracked files 表示工作区有新文件,但 Git 尚未开始追踪它。git add 就是将文件加入追踪,并放入暂存区。
2.1 git add:添加至暂存区
git add readme.txt
再运行 git status:

readme.txt 已经进入暂存区,等待被提交。此时如果你修改 readme.txt,比如加一行 作者:小明,再查看状态:

出现了两个区域:已暂存的修改(首次添加时的版本),和未暂存的修改(新增作者那一行)。想让新修改也加入暂存区,需要再次 git add。
2.2 git commit:提交至版本库
现在把暂存区的内容正式存入版本库,形成一次快照:
git commit -m "第一次提交:新建readme.txt"
-m 后面跟着的是提交说明(commit message)。这是非常重要的习惯:好的提交说明能让你半年后回来还能看懂当时做了什么。建议用中文或英文简明扼要地描述变动,如“添加用户登录接口”而不是“改了点东西”。
运行后输出:

那一长串 933c29a[ 是提交的 SHA-1 哈希值(缩写),是这次提交的全球唯一身份证。
三、查看历史:git log 的十八般武艺
有了提交,就可以翻阅历史。最简单的:
git log
会输出提交的作者、日期和说明。但更常用的是一行显示:
git log –oneline
效果:

如果想看漂亮的图形化分支历史(后续学分支时会很爽):
git log –oneline –graph –all
再比如,你想看某次提交到底改了哪些内容:
git log -p
-p 代表 patch,显示每次提交的具体差异。

四、工作区与暂存区的比较:git diff
修改一下 readme.txt,给第一行末尾加上 – 学习Git,保存。但先别 git add。想知道自己到底改了什么,用:
git diff
你会看到类似这样的输出:

diff 比较的是工作区与暂存区的差异。如果你已经 git add 过,想看看暂存区和版本库最后一次提交的差异,使用:
git diff –staged

这个命令在你提交前做最后检查时非常有用。
五、救命操作:撤销修改
这是小白最需要的章节,请一定逐字阅读。犯错是必然的,关键是如何优雅地撤销。
5.1 撤销工作区修改:git restore
假设你改乱了某个文件,想把它恢复成暂存区(或版本库)的样子。在旧版 Git 中使用 git checkout — <file>,新版推荐使用:
git restore readme.txt
这个操作会丢弃工作区所有未暂存的修改,不可恢复,执行前请确认。
5.2 撤销暂存区修改(unstage)
如果你已经 git add 了,但还没 commit,想把它移出暂存区:
git restore –staged readme.txt
这样文件会回到修改状态,但仍保留在工作区。相当于“把纸箱里的东西拿出来放回地上”。
5.3 撤销最近一次提交(未推送)
假设你刚刚提交完,发现写错了说明,或者漏了一个文件,想修改最近一次提交:
git commit -m "错误的说明"
# 如果想修改说明,或者把漏掉的文件也加入这次提交:
git add 漏掉的文件
git commit –amend -m "正确的说明"
–amend 会用新的提交覆盖掉上一次提交,注意:如果这次提交已经推送到远程仓库,就不要用 –amend 了,不然会引发冲突。
5.4 版本回退:git reset
如果想彻底回到历史中的某次提交,丢掉后面的所有提交:
git reset –hard 提交ID
比如 git reset –hard e8a7d4f。–hard 意味着工作区和暂存区都会被重置为那次提交的状态,未提交的改动全部消失,请谨慎使用。
还有一种更安全的方式 git revert,它会生成一个新的提交来“撤销”某个提交,而不是修改历史。协作环境下优先使用 revert。
六、忽略不该追踪的文件:.gitignore
项目中总有些文件不需要追踪:编译产生的 .class、node_modules、操作系统临时文件、带有密码的配置文件等。在仓库根目录下创建 .gitignore 文件:
# .gitignore 示例
*.log
node_modules/
.DS_Store
config/database.yml
规则很简单:
-
*.log 忽略所有扩展名为 log 的文件
-
node_modules/ 忽略这个目录
-
以 / 开头表示只忽略根目录下的文件
.gitignore 本身需要提交到仓库,这样整个团队共享一份忽略规则。
七、一次完整的工作流演练
为了巩固上面所有的知识,我们进行一次完整的操作:
# 1. 仓库初始化(已经做过)
cd ~/Desktop/my-first-git
# 2. 创建 .gitignore
echo "*.log" > .gitignore
echo "temp/" >> .gitignore
# 3. 创建新文件并编写内容
echo "print('hello git')" > hello.py
# 4. 查看状态
git status
# 5. 添加所有修改到暂存区
git add .
# 6. 提交
git commit -m "添加 hello.py 和 .gitignore"
# 7. 修改 hello.py
echo "print('second line')" >> hello.py
# 8. 查看差异
git diff
# 9. 暂存并再次提交
git add hello.py
git commit -m "在 hello.py 中添加第二行"
# 10. 查看历史
git log –oneline


至此,你已经亲手操作了一次完整的“修改→暂存→提交”循环。
总结
Git 有三区:工作区(修改文件)、暂存区(准备提交的清单)、版本库(永久快照)。理解这个模型是掌握 Git 的关键。
git add 将修改加入暂存区,git commit 将暂存区提交至版本库。
git status 随时查看各区状态,git diff 查看差异。
撤销三法宝:git restore 恢复工作区,git restore –staged 取消暂存,git reset –hard 版本回退(危险)。
.gitignore 用于排除不需要追踪的文件。
提交说明要清晰有意义,–amend 可修改最近一次提交(未推送时)。
如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享,也可以留言告诉我你遇到的其它问题,我会尽快回复。动手练习是掌握编程最快的方法,请务必亲手敲一遍本文的所有示例代码,并截图保存你的成果。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。




