🔍 1. 工作区 vs 暂存区(vs stash)
⚠️ 纠正一个常见误解:
git stash不是“暂存区” !它是 独立的“储藏区” 。
✅ Git 的三个核心区域
表格
| 区域 | 英文 | 作用 | 命令示例 |
|---|---|---|---|
| 工作区 | Working Directory | 你正在编辑的文件(磁盘上的实际文件) | vim file.java |
| 暂存区 | Staging Area / Index | 准备下一次提交的快照(git add 后进入这里) | git add . |
| 版本库 | Repository (.git) | 所有 commit 历史存储的地方 | git commit |
📌 关键区别
git add→ 把 工作区 的修改 → 暂存区git commit→ 把 暂存区 的内容 → 版本库(生成新 commit)git stash→ 把 工作区 + 暂存区 的修改 → 临时储藏栈(不生成 commit)
💡 类比:
- 工作区 = 你的草稿纸
- 暂存区 = 提交前的“打包箱”(你决定哪些放进箱子)
stash= 临时抽屉(把当前草稿和箱子都塞进去,等会儿再拿出来)
🔁 2. git reset vs git revert
表格
| 特性 | git reset | git revert |
|---|---|---|
| 本质 | 移动 HEAD 指针(改写历史) | 创建新 commit 来抵消旧 commit(保留历史) |
| 是否改变历史 | ✅ 是(危险!) | ❌ 否(安全) |
| 适用场景 | 本地未推送的 commit | 已推送/共享分支的 commit |
| 协作影响 | 会导致他人代码混乱 | 安全,适合团队 |
| 命令示例 | git reset --hard HEAD~1 | git revert HEAD |
✅ 使用原则:
- 未 push 的代码 → 用
reset(干净利落) - 已 push 的代码 → 用
revert(尊重协作)
💡 记住:
“Reset is for local, Revert is for shared.”
🕰️ 3. git reflog —— 你的“后悔药”
✅ 是什么?
- 记录 HEAD 指针的所有变化(包括 reset、checkout、merge 等)
- 即使
git log看不到的 commit,reflog也能找回!
🔧 常用命令:
bash
编辑
git reflog # 查看所有 HEAD 变动
git reflog show HEAD@{1} # 查看上一次 HEAD 状态
git reset --hard HEAD@{2} # 回到 reflog 中第 2 条记录
🛟 恢复误操作示例:
bash
编辑
# 你不小心 hard reset 丢代码了
git reset --hard a1b2c3d
# 用 reflog 找回
git reflog
# 输出:
# a1b2c3d HEAD@{0}: reset: moving to a1b2c3d
# e4f5g6h HEAD@{1}: commit: 我的重要提交 ← 这个就是丢掉的!
# 恢复
git reset --hard e4f5g6h
⏳ 注意:reflog 默认保留 30 天(可配置)
📊 4. git reset 四种模式终极对比表
表格
| 模式 | 命令 | HEAD | 暂存区 | 工作区 | 典型用途 | 安全性 |
|---|---|---|---|---|---|---|
| soft | git reset --soft <commit> | ✅ 移动 | ✅ 保留 | ✅ 保留 | 撤销 commit,保留 add 内容 (合并多个 commit) | ⭐⭐⭐⭐⭐ |
| mixed (默认) | git reset --mixed <commit> 或 git reset <commit> | ✅ 移动 | ❌ 清空 | ✅ 保留 | 撤销 commit + add,重新选择文件 | ⭐⭐⭐⭐ |
| hard | git reset --hard <commit> | ✅ 移动 | ❌ 清空 | ❌ 丢弃 | 彻底回到某状态 (放弃所有本地修改) | ⭐(危险!) |
| keep | git reset --keep <commit> | ✅ 移动 | ❌ 清空 | ⚠️ 仅保留未冲突文件 | 类似 hard,但如果有未提交修改会失败(更安全) | ⭐⭐⭐ |
💡
--keep的特殊行为:
- 如果工作区有修改,且这些修改与目标 commit 不冲突 → 保留
- 如果有冲突 → 拒绝执行(避免意外覆盖)
🆚 --hard vs --keep
bash
编辑
# 假设你修改了 file.txt,但没 add/commit
git reset --hard HEAD~1 # file.txt 被强制覆盖!
git reset --keep HEAD~1 # 报错:Cannot reset with uncommitted changes
✅ 建议:日常用
--keep代替--hard,更安全!
✅ 小团队黄金法则总结
表格
| 场景 | 推荐命令 |
|---|---|
| 撤销本地 commit,重新提交 | git reset --soft HEAD~1 |
| 撤销 commit 并重新选择文件 | git reset HEAD~1(= mixed) |
| 放弃所有本地修改 | git reset --keep HEAD(比 hard 安全) |
| 已 push 的错误提交 | git revert <commit-id> |
| 误操作后找回代码 | git reflog → git reset --hard <old-commit> |
💡 终极口诀:
“Soft 保暂存,Mixed 保工作,Hard 全丢掉,Keep 更可靠;
本地用 Reset,共享用 Revert;
丢了别慌张,Reflog 来帮忙!”