Git 中的各种恢复
分类 | 计算机技术 |
---|---|
标签 | #git |
最后编辑时间 | 2023/05/25 14:03 |
状态 | 已发布 |
创建时间 | 2023/05/19 18:09 |
前置知识
git 有三个区域,分别为工作区(working-tree),暂存区(stage)和历史区(history-tree)。
常见的操作为:
-
在工作区做修改
-
通过 git add 命令添加到暂存区
-
通过 git commit 命令提交到历史区
常见场景
撤销工作区的修改
-
git restore
撤销 git add
git add 的本质是更新了暂存区的索引,默认情况下,暂存区的索引和历史区一致,git add 更新暂存区后,git status 会显示当前暂存区和历史区的差异,这部分差异即为 git add 的结果。
因此撤销 git add 的本质就是从历史区恢复暂存区的索引。
git restore --staged
可以做到这一点。
和
git restore
🖼️ 图片做对比
撤销 git commit
git commit 的本质是把暂存区的索引提交到历史区。
撤销 commit 的本质就是让 HEAD 指向要撤销的 commit 的前一个 commit 即可。
git reset --[soft|mixed|hard] HEAD^
都能回退到 HEAD^ (上一个commit),区别如下:
-
soft: 不改变当前工作区的内容,不改变暂存区的内容。
-
mixed: 不改变当前工作区的内容,改变暂存区的内容。
-
hard: 改变当前工作区的内容,改变暂存区的内容。
组合拳
- 场景一: commit 前发现有个文件不该放到该次 commit
git restore --staged <pathspec> # 将文件踢出暂存区 git commit -m 'bla bla' # commit
- 场景二: commit 后发现内容写错了
git reset --soft HEAD^ # 撤销 commit git commit -m 'bla bla' # 重新 commit # 或者 git commit --amend
- 场景三: commit 后发现有些文件不该放到该次 commit
- 拳法一: 不该放的文件比较少
git reset --soft HEAD^ # 撤销 commit git restore --staged <pathspec> # 将不合群的文件踢出暂存区 git commit -m 'bla bla' # 重新 commit
- 拳法二: 不该放的文件比较多
git reset HEAD^ # 撤销 commit git add <pathspec> # 将合群的文件加入暂存区 git commit -m 'bla bla' # 重新 commit
- 拳法一: 不该放的文件比较少
- 场景四: 撤销工作区的修改
git restore <pathspec>
一点建议
- git reset 也可以用来撤销 git add ,但 git reset 的本意是为了操控历史区,其对暂存区和工作区的操作算是副作用。我们使用 git reset 来撤销 git add,即从HEAD 恢复暂存区的内容,本质上是使用 git reset HEAD,回退 commit 到 HEAD,相当于没有回退,只是使用其同时能撤销暂存区的修改的副作用。
- 此外,git checkout 所承载的功能非常之多,最常用的就是用于切换分支,但同时却也能撤销工作区的修改,这很令人困惑,并且该操作很危险,比如当执行 git checkout dev 时,你不知道其是切换到 dev 分支,还是撤销 dev 文件的修改。因此,git restore 被引入,该命令的本意就如同其名称所隐含的那样:恢复。因此,我个人建议使用 git restore 来恢复工作区或者暂存区。(另外使用新的命令 git switch 来切换分支)
- 一定要慎用 git reset —hard 和 git restore ,这两个命令会丢弃工作区的内容,请注意是永久性的丢弃工作区的内容!
2023-01-01