Git reset 与 restore
1. reset 和 restore 是干什么的
Git 中:
text
reset和:
text
restore都可以用于“撤销”操作。
但它们处理的对象不一样。
可以先简单记住:
text
restore
主要恢复文件
reset
主要重置提交位置和暂存区如果再细一点:
text
git restore
主要处理工作区和暂存区中的文件
git reset
主要处理 HEAD、暂存区,有时也会影响工作区restore
2. git restore 是什么
git restore 主要用于恢复文件。
常见用途:
text
放弃工作区修改
取消 git add
从某个提交恢复文件它更偏向:
text
文件级操作3. 放弃工作区修改
假设:
text
main.py已经被 Git 跟踪。
你修改了它:
bash
nvim main.py查看:
bash
git status可能看到:
text
Changes not staged for commit:
modified: main.py如果这些修改不要了:
bash
git restore main.pyGit 会把:
text
main.py恢复到最近一次提交的状态。
4. git restore 会丢失修改
例如:
text
最近一次 commit
↓
main.py 原始内容
↓
你修改 main.py执行:
bash
git restore main.py之后:
text
你刚才的未提交修改会被覆盖。
所以使用前建议:
bash
git diff先看看改了什么。
5. 恢复多个文件
可以:
bash
git restore main.py app.py恢复当前目录下所有已跟踪文件:
bash
git restore .这里:
text
.表示当前目录。
6. git restore --staged
假设:
bash
git add main.py现在文件已经进入:
text
暂存区查看:
bash
git status可能看到:
text
Changes to be committed:
modified: main.py如果只是想取消:
bash
git add可以:
bash
git restore --staged main.py结果:
text
main.py会离开暂存区。
但是:
text
文件中的修改仍然存在7. restore 两个最重要的命令
放弃文件修改
bash
git restore main.py作用:
text
工作区 → 恢复修改会消失。
取消暂存
bash
git restore --staged main.py作用:
text
暂存区 → 工作区修改还在。
8. 一个完整例子
假设修改:
text
main.py然后:
bash
git status显示:
text
modified: main.py执行:
bash
git add main.py现在:
text
工作区
↓
暂存区如果后悔了:
bash
git restore --staged main.py文件重新变成未暂存状态。
如果连代码修改也不要了:
bash
git restore main.py这样修改就完全被丢弃。
所以:
text
git restore --staged main.py
↓
取消 add
git restore main.py
↓
放弃修改reset
9. git reset 是什么
git reset 主要用于:
text
移动 HEAD
重置暂存区
重置工作区它比:
text
git restore影响范围更大。
因此使用时需要更谨慎。
10. 什么是 HEAD
Git 中:
text
HEAD可以简单理解为:
text
当前所在的提交例如提交历史:
text
A ← B ← C
↑
HEAD当前在:
text
C那么:
text
HEAD就是:
text
C11. HEAD~1
text
HEAD~1表示当前提交的上一个提交。
例如:
text
A ← B ← C
↑ ↑
HEAD~1 HEAD同理:
text
HEAD~2表示:
text
当前提交往前两个提交12. git reset 三种模式
最常见:
text
--soft
--mixed
--hard可以先记住:
| 模式 | Commit | 暂存区 | 工作区 |
|---|---|---|---|
--soft | 回退 | 保留 | 保留 |
--mixed | 回退 | 重置 | 保留 |
--hard | 回退 | 重置 | 重置 |
reset --soft
13. git reset --soft
例如:
bash
git reset --soft HEAD~1表示:
text
撤销最近一次 commit但是:
text
修改仍然保留
并且仍然处于暂存区14. --soft 示例
原来:
text
工作区
↓ git add
暂存区
↓ git commit
提交 C执行:
bash
git reset --soft HEAD~1之后:
text
提交 C 被撤销
但是 C 中的修改仍在暂存区所以可以直接重新:
bash
git commit -m "new message"15. --soft 适合什么情况
例如提交信息写错:
bash
git commit -m "udpate"发现:
text
udpate拼错了。
可以:
bash
git reset --soft HEAD~1然后:
bash
git commit -m "update"不过如果只是修改最近一次 commit 信息,更简单的是:
bash
git commit --amendreset --mixed
16. git reset --mixed
执行:
bash
git reset --mixed HEAD~1会:
text
撤销 commit
取消暂存
保留工作区修改也就是说:
text
代码还在
但需要重新 git add17. --mixed 是默认模式
下面两个命令:
bash
git reset HEAD~1和:
bash
git reset --mixed HEAD~1通常效果相同。
所以:
text
git reset默认就是:
text
--mixed18. --mixed 示例
原本:
text
main.py
↓
git add
↓
git commit执行:
bash
git reset HEAD~1之后:
text
commit 被撤销
main.py 修改仍然存在
但已经不在暂存区查看:
bash
git status可能看到:
text
Changes not staged for commit:
modified: main.pyreset --hard
19. git reset --hard
例如:
bash
git reset --hard HEAD~1会:
text
回退 commit
重置暂存区
重置工作区也就是说:
text
提交后的修改
可能直接全部消失这是三种模式中最危险的一种。
20. --hard 示例
假设:
text
A ← B ← C
↑
HEAD执行:
bash
git reset --hard HEAD~1变成:
text
A ← B
↑
HEAD并且工作区也恢复成:
text
B对应的状态。
21. --hard 为什么危险
因为它不仅移动:
text
HEAD还会直接修改:
text
工作区文件例如你有重要的未提交代码:
text
main.py执行:
bash
git reset --hard这些修改可能会直接丢失。
所以在执行之前一定先看:
bash
git status以及:
bash
git diffreset 到指定提交
22. 使用 commit hash
先查看:
bash
git log --oneline例如:
text
9a021bc add login
713bc19 add README
27fd621 initial commit可以:
bash
git reset --soft 713bc19或者:
bash
git reset --mixed 713bc19或者:
bash
git reset --hard 713bc19具体效果取决于模式。
reset 与暂存区
23. git reset 取消暂存
以前经常使用:
bash
git reset HEAD main.py把:
text
main.py从暂存区移出来。
现代 Git 更推荐:
bash
git restore --staged main.py因为语义更明确。
所以新项目中可以优先记:
bash
git restore --staged main.pyreset 到远程分支
24. git reset --hard origin/main
这是非常常见的一条命令:
bash
git fetch origin
git reset --hard origin/main意思是:
text
让当前本地分支
完全变成远程 origin/main 的状态25. 使用场景
例如:
text
Mac负责开发并 push。
Linux 机器只负责同步。
Linux 本地出现:
text
修改
冲突
lazy-lock.json 变化而这些本地修改完全不需要。
那么:
bash
git fetch origin
git reset --hard origin/main就可以让当前分支直接和:
text
origin/main保持一致。
26. reset --hard 不会删除未跟踪文件
这一点非常重要。
例如项目:
text
project/
├── main.py
└── test.txt其中:
text
test.txt是:
text
Untracked即未被 Git 跟踪。
执行:
bash
git reset --hard origin/main通常不会删除:
text
test.txt因为:
text
reset主要处理 Git 已经跟踪的内容。
27. 删除未跟踪文件需要 git clean
如果还想删除所有未跟踪文件:
bash
git clean -fd所以完整同步流程:
bash
git fetch origin
git reset --hard origin/main
git clean -fd效果可以理解成:
text
已跟踪文件
→ 完全按照 origin/main
未跟踪文件
→ 删除restore 与 reset 的区别
28. 最核心区别
git restore
主要:
text
操作文件例如:
bash
git restore main.py恢复文件。
bash
git restore --staged main.py取消暂存。
git reset
主要:
text
移动 HEAD
重置暂存区
必要时重置工作区例如:
bash
git reset --soft HEAD~1撤销 commit,但保留暂存。
29. 对比表
| 命令 | 主要作用 |
|---|---|
git restore file | 放弃工作区修改 |
git restore --staged file | 取消暂存 |
git reset --soft | 回退提交,保留暂存和修改 |
git reset --mixed | 回退提交,取消暂存,保留修改 |
git reset --hard | 回退提交并丢弃修改 |
一套完整流程理解
30. Git 的三个区域
先记住:
text
工作区
↓ git add
暂存区
↓ git commit
本地仓库那么:
restore
主要在:
text
工作区 ↔ 暂存区之间处理文件。
reset
主要从:
text
本地仓库往回调整:
text
HEAD
暂存区
工作区31. 场景一:代码写错了,还没 add
状态:
text
工作区有修改想全部不要:
bash
git restore main.py32. 场景二:不小心 git add
执行了:
bash
git add main.py但是暂时不想提交:
bash
git restore --staged main.py修改仍然保留。
33. 场景三:commit 错了,但代码要留着
如果想保留暂存状态:
bash
git reset --soft HEAD~1如果想取消暂存,但代码继续保留:
bash
git reset HEAD~134. 场景四:最近一次提交和代码全部不要
bash
git reset --hard HEAD~1注意:
text
代码修改会被删除使用前一定确认。
35. 场景五:本地完全覆盖成 GitHub 版本
bash
git fetch origin
git reset --hard origin/main如果连未跟踪文件也要清掉:
bash
git clean -fdrevert 和 reset
36. 已经 push 的提交不要轻易 reset
如果某个 commit:
text
已经 push 到 GitHub并且其他人可能已经基于它继续开发,
通常不建议直接:
bash
git reset然后强制 push。
因为这样会:
text
改写 Git 历史多人协作时很容易造成问题。
37. git revert
对于已经共享出去的提交,更常见的是:
bash
git revert commit_hash例如:
bash
git revert 9a021bc它不会删除原来的提交。
而是创建一个:
text
新的 commit用于撤销之前的修改。
38. reset 和 revert 的区别
reset
text
移动历史例如:
text
A ← B ← Creset 到 B:
text
A ← Brevert
原来:
text
A ← B ← Crevert C:
text
A ← B ← C ← D其中:
text
D负责撤销 C 的修改。
因此:
text
reset
更适合本地、尚未共享的历史
revert
更适合已经 push 的提交常见危险命令
39. git reset --hard
bash
git reset --hard HEAD~1可能删除:
text
未提交修改
提交后的代码执行前至少:
bash
git status
git diff40. git restore .
bash
git restore .会放弃当前目录下大量未暂存修改。
所以也需要谨慎。
41. git clean -fd
bash
git clean -fd会删除未跟踪文件和目录。
推荐先预览:
bash
git clean -nd确认后再:
bash
git clean -fd命令速查
42. restore
放弃一个文件修改:
bash
git restore main.py放弃当前目录修改:
bash
git restore .取消暂存:
bash
git restore --staged main.py43. reset
撤销最近一次 commit,修改保持暂存:
bash
git reset --soft HEAD~1撤销最近一次 commit,修改保留但取消暂存:
bash
git reset HEAD~1撤销最近一次 commit,并丢弃修改:
bash
git reset --hard HEAD~1同步远程:
bash
git fetch origin
git reset --hard origin/main44. 最简单的记忆方法
restore
看到:
text
restore想到:
text
恢复文件最常见:
bash
git restore filereset
看到:
text
reset想到:
text
重置 Git 状态 / 提交位置最常见:
bash
git reset --soft HEAD~1
git reset HEAD~1
git reset --hard HEAD~145. soft、mixed、hard 记忆
最容易记的方式:
text
soft
最温柔
代码和暂存都留下
mixed
中等
代码留下,暂存取消
hard
最狠
代码也恢复对应:
text
commit staged working tree
--soft × ✓ ✓
--mixed × × ✓
--hard × × ×这里:
text
✓ = 保留
× = 重置小结
restore 和 reset 最核心的区别:
text
restore
主要恢复文件
reset
主要重置提交和 Git 状态日常最常用的几个命令:
bash
git restore file放弃未暂存修改。
bash
git restore --staged file取消:
text
git add但保留代码。
bash
git reset --soft HEAD~1撤销 commit,但保留暂存。
bash
git reset HEAD~1撤销 commit,保留代码。
bash
git reset --hard HEAD~1撤销 commit,同时丢弃代码修改。
如果本地机器只想完全跟随远程:
bash
git fetch origin
git reset --hard origin/main
git clean -fd最后记住:
text
不确定时先 git status
危险操作前先 git diff特别是:
text
git restore .
git reset --hard
git clean -fd都可能导致本地修改丢失。