本节目标
这一节要解决开发工程师每天都会遇到的问题:
我到底改了什么?
哪些修改准备提交?
哪些修改不应该提交?
改错了能不能撤销?
学完这一节,你应该能熟练使用:
git status
git diff
git diff --cached
git add
git restore
git restore --staged
1. 为什么必须学会看 diff
在真实开发中,提交代码前不能只执行:
git add .
git commit -m "修改"
这样很危险,因为你可能把以下内容一起提交上去:
-
临时代码
-
调试日志
-
测试用账号密码
-
不相关文件
-
格式化造成的大量无关改动
-
自己还没验证过的代码
所以,一个成熟开发工程师提交前一定会先看:
git status
git diff
核心习惯是:
先看状态,再看差异,确认无误后再提交。
2. 复习 Git 的三个本地区域
Git 本地最重要的是三个区域:
工作区 -> 暂存区 -> 本地仓库
对应操作是:
修改文件 -> git add -> git commit
可以这样理解:
| 区域 | 含义 | 常用命令 |
|---|---|---|
| 工作区 | 你正在编辑的文件 | git status, git diff |
| 暂存区 | 准备进入下一次提交的修改 | git add, git diff --cached |
| 本地仓库 | 已经保存下来的提交历史 | git commit, git log |
3. git status:先看当前状态
git status 是最常用的 Git 命令之一。
git status
它会告诉你:
-
当前在哪个分支
-
哪些文件被修改了
-
哪些文件还没有被 Git 跟踪
-
哪些修改已经进入暂存区
-
有没有东西可以提交
常见状态有三种。
3.1 Untracked files
Untracked files:
readme.txt
意思是:
这个文件是新文件,Git 还没有跟踪它。
如果你想让 Git 管理它:
git add readme.txt
3.2 Changes not staged for commit
Changes not staged for commit:
modified: readme.txt
意思是:
文件已经被修改,但还没有放入暂存区。
这时可以用:
git diff
查看具体改了什么。
3.3 Changes to be committed
Changes to be committed:
modified: readme.txt
意思是:
这些修改已经进入暂存区,下一次 commit 会包含它们。
这时可以用:
git diff --cached
查看即将提交的内容。
4. git diff:查看工作区改了什么
执行:
git diff
它查看的是:
工作区 与 暂存区 之间的差异
也就是说,它显示的是:
你改了但还没有 git add 的内容。
例如你有一个文件:
hello git
然后你追加一行:
hello git
second line
执行:
git diff
你可能看到:
hello git
+second line
其中:
+ 表示新增的行
- 表示删除的行
5. git diff --cached:查看暂存区内容
当你执行:
git add readme.txt
再执行:
git diff
你可能发现没有输出。
这不是因为没有修改,而是因为修改已经进入暂存区了。
这时应该执行:
git diff --cached
它查看的是:
暂存区 与 最新提交 之间的差异
也就是:
下一次 commit 准备提交什么。
6. git add 的真正含义
很多新手以为:
git add = 添加文件
其实更准确地说:
git add = 把当前修改放进暂存区
它不仅能添加新文件,也能添加已修改文件,还能记录删除操作。
例如:
git add readme.txt
意思是:
把 readme.txt 当前这一刻的修改,放进下一次提交。
注意这里有一个细节:
git add 记录的是执行 add 那一刻的文件状态。
如果你 git add 后又继续修改同一个文件,那么这个文件会同时存在两部分变化:
一部分已经在暂存区
一部分还留在工作区
这时:
git diff --cached
查看已经暂存的部分。
git diff
查看还没有暂存的部分。
7. 撤销工作区修改
如果你改错了文件,并且这个修改还没有 git add,可以使用:
git restore readme.txt
作用是:
丢弃 readme.txt 在工作区的修改,恢复到暂存区或最新提交的状态。
危险点:
这个操作会丢弃你的本地修改。
如果修改内容还有用,不要随便执行。
如果要撤销所有工作区修改:
git restore .
新手阶段不建议随便用 git restore .,因为它会一次性丢弃当前目录下所有未暂存修改。
8. 取消暂存
如果你已经执行了:
git add readme.txt
但后来发现这个文件不应该进入下一次提交,可以执行:
git restore --staged readme.txt
作用是:
把 readme.txt 从暂存区拿出来,但保留工作区里的修改。
注意:
git restore --staged 不会删除你的代码修改。
它只是取消暂存。
这和 git restore readme.txt 不一样。
9. 两种 restore 的区别
| 命令 | 作用 | 是否丢失修改 |
|---|---|---|
git restore 文件名 |
撤销工作区修改 | 会丢失未暂存修改 |
git restore --staged 文件名 |
取消暂存 | 不会丢失修改 |
简单记忆:
带 --staged:只动暂存区,不动你的文件内容。
不带 --staged:会改动工作区文件内容。
10. 真实开发中的提交前检查流程
一个比较好的工程习惯是:
git status
git diff
git add <需要提交的文件>
git diff --cached
git commit -m "清楚描述这次修改"
含义是:
先看当前有哪些文件变了
再看每个文件具体改了什么
只添加这次任务需要提交的文件
再检查即将提交的内容
最后提交
不要一上来就使用:
git add .
git add . 本身不是错误,但你必须先知道它会添加哪些修改。
11. 实战练习一:查看 diff
创建一个练习仓库:
mkdir git-diff-demo
cd git-diff-demo
git init
创建文件:
echo "hello git" > readme.txt
git add readme.txt
git commit -m "添加 readme 文件"
修改文件:
echo "second line" >> readme.txt
查看状态:
git status
查看差异:
git diff
把修改加入暂存区:
git add readme.txt
再次查看普通 diff:
git diff
查看暂存区 diff:
git diff --cached
提交:
git commit -m "补充 readme 内容"
12. 实战练习二:取消暂存
修改文件:
echo "third line" >> readme.txt
加入暂存区:
git add readme.txt
查看状态:
git status
取消暂存:
git restore --staged readme.txt
再次查看状态:
git status
你会看到文件从:
Changes to be committed
回到了:
Changes not staged for commit
但是文件内容仍然保留。
13. 实战练习三:撤销工作区修改
假设你不想要刚才的修改了:
git restore readme.txt
再查看状态:
git status
如果没有其他修改,Git 会提示:
nothing to commit, working tree clean
意思是:
当前工作区是干净的,没有需要提交的修改。
14. 新手常见错误
错误一:不看 diff 就提交
错误习惯:
git add .
git commit -m "update"
正确习惯:
git status
git diff
git add <文件>
git diff --cached
git commit -m "说明本次修改目的"
错误二:把不相关文件一起提交
一次提交应该只做一件事。
例如修复登录问题时,不要顺手提交:
格式化整个项目
修改数据库配置
调整页面颜色
删除测试文件
这些应该拆成不同的提交。
错误三:把临时调试代码提交
提交前要检查是否有:
Console.WriteLine(...)
MessageBox.Show("test")
临时账号
临时密码
无用注释
错误四:误用 git restore
git restore 文件名 会丢弃工作区修改。
如果你只是想取消暂存,应该用:
git restore --staged 文件名
15. 和 Gerrit 的关系
Gerrit 对提交质量要求更高。
你推送到 Gerrit 前,最好先检查:
git status
git diff --cached
git log --oneline
然后再推送:
git push origin HEAD:refs/for/master
如果你提交了不相关代码,评审者很容易指出:
这个文件为什么也改了?
这个调试日志为什么提交了?
这个提交是不是太大了?
请拆分成多个 Change。
所以学会看 diff,是进入 Gerrit 工作流的基础。
16. 本节必须记住的命令
git status
git diff
git diff --cached
git add <文件>
git restore <文件>
git restore --staged <文件>
对应含义:
git status 查看当前状态
git diff 查看未暂存修改
git diff --cached 查看已暂存修改
git add <文件> 加入暂存区
git restore <文件> 撤销工作区修改
git restore --staged <文件> 取消暂存
17. 本节总结
这一节的核心不是背命令,而是形成工程习惯:
提交前一定要知道自己改了什么。
提交前一定要知道自己准备提交什么。
不要把不相关修改混进同一个提交。
不要随便丢弃工作区修改。
真正的开发工程师不是只会写代码,还要能清楚、干净、可审查地提交代码。
下一节建议学习:
Git 分支 branch、switch、merge,以及为什么不要直接在 master/main 上开发。