ToB企服应用市场:ToB评测及商务社交产业平台

标题: Git -- reset 详解 [打印本页]

作者: 北冰洋以北    时间: 2024-7-30 17:24
标题: Git -- reset 详解
弁言

当我们在项目中有多个人协同开辟时候,不免会出现一些错误的提交大概删除了一些重要文件。我们需要回滚到指定的某一个节点。那些七零八落的各种提交都要清撤消。
这时候,我们的指令就要用到了。reset

正文


git reset。它的一句话概括
  1. git-reset - Reset current HEAD to the specified state
复制代码
意思就是可以让HEAD这个指针指向其他的地方。例如我们有一次commit不是不是很满意,需要回到上一次的Commit里面。那么这个时候就需要通过reset,把HEAD指针指向上一次的commit的点。
它有三种模式,soft,mixed,hard,具体的使用方法下面这张图,展示的很全面。

别的git reset --hard HEAD^
等价于git reset --hard xxx(xxx为commit id)





git各个区域和下令关系

这三个模式理解了,对于使用这个下令很有帮助。在理解这三个模式之前,需要略微知道一点Git的根本流程。正如上图,Git会有三个区域:



文件存入Repository流程
以下简单敘述一下把文件存入Repository流程:
实战演示

reset --hard:重置stage区和工作目录:

reset --hard 会在重置 HEAD 和branch的同时,重置stage区和工作目录里的内容。当你在 reset 后面加了 --hard 参数时,你的stage区和工作目录里的内容会被完全重置为和HEAD的新位置雷同的内容。换句话说,就是你的没有commit的修改会被全部擦掉。
例如你在上次 commit 之后又对文件做了一些改动:把修改后的ganmes.txt文件addstage区,修改后的shopping list.txt保留在工作目录
  1. git status
复制代码


最初状态
然后,你实行了reset并附上了--hard参数:
  1. git reset --hard HEAD^
复制代码
你的 HEAD 和当前 branch 切到上一条commit 的同时,你工作目录里的新改动和已经add到stage区的新改动也一起全都消失了:
  1. git status
复制代码


reset --hard head^之后
可以看到,在 reset --hard 后,所有的改动都被擦掉了。
reset --soft:保留工作目录,并把重置 HEAD 所带来的新的差异放进暂存区

reset --soft 会在重置 HEAD 和 branch 时,保留工作目录和暂存区中的内容,并把重置 HEAD 所带来的新的差异放进暂存区。
什么是「重置 HEAD 所带来的新的差异」?就是这里:

由于 HEAD 从 4 移动到了 3,而且在 reset 的过程中工作目录和暂存区的内容没有被清理掉,所以 4 中的改动在 reset 后就也成了工作目录新增的「工作目录和 HEAD 的差异」。这就是上面一段中所说的「重置 HEAD 所带来的差异」。
此模式下会保留 working tree工作目录的內容,不会改变到现在所有的git管理的文件夹的內容;也会
保留 index暂存区的內容,让 index 暂存区与 working tree 工作目录的內容是一致的。就只有 repository 中的內容的更变需要与 reset 目标节点一致,因此原始节点与reset节点之间的差异变更聚集会存在与index暂存区中(Staged files),所以我们可以直接实行 git commit 將 index暂存区中的內容提交至 repository 中。当我们想合并「当前节点」与「reset目标节点」之间不具太大意义的 commit 记录(可能是阶段性地频繁提交)時,可以考虑使用 Soft Reset 来让 commit 演进线图较为清晰点。

所以在同样的情况下,还是老样子:把修改后的ganmes.txt文件addstage区,修改后的shopping list.txt保留在工作目录
  1. git status
复制代码


最初状态

假设此时当前 commit 的改动内容是新增了 laughters.txt 文件:
  1. git show --stat
复制代码

git show --stat


如果这时你实行:
  1. git reset --soft HEAD^
复制代码
那么除了 HEAD 和它所指向的 branch1 被移动到 HEAD^ 之外,原先 HEAD 处 commit 的改动(也就是谁人 laughters.txt 文件)也会被放进暂存区:
  1. git status
复制代码


使用git reset --soft HEAD^

这就是--soft 和 --hard 的区别:--hard 会清空工作目录和暂存区的改动,*而 --soft则会保留工作目录的内容,并把由于保留工作目录内容所带来的新的文件差异放进暂存区
reset 不加参数(mixed):保留工作目录,并清空暂存区

reset 如果不加参数,那么默认使用 --mixed 参数。它的举动是:保留工作目录,并且清空暂存区。也就是说,工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录。简而言之,就是「把所有差异都混淆(mixed)放在工作目录中」。
还以同样的情况为例:
  1. git status
复制代码

最初状态
修改了 的games.txt 和 shopping list.txt,并把 games.txt 放进了暂存区。
  1. git show --stat
复制代码

git show --stat


最新的 commit 中新增了 laughters.txt 文件。
这时如果你实行无参数reset大概带--mixed参数:
  1. [/code] [list=1]
  2. [*] git reset HEAD^
  3. [*] git reset --mixed HEAD^
  4. [/list] 工作目录的内容和 [b]--soft[/b] 一样会被保留,但和 [b]--soft[/b] 的区别在于,它会把暂存区清空,并把原节点和[b]reset[/b]节点的差异的文件放在工作目录,总而言之就是,工作目录的修改、暂存区的内容以及由 [b]reset[/b] 所导致的新的文件差异,都会被放进工作目录
  5. [code]git status
复制代码

git reset HEAD^之后
总结

reset 的本质:移动 HEAD 以及它所指向的 branch

实质上,reset 这个指令虽然可以用来撤销 commit ,但它的实质举动并不是撤销,而是移动 HEAD ,并且「捎带」上 HEAD 所指向的 branch(如果有的话)。也就是说,reset 这个指令的举动其实和它的字面意思 "reset"(重置)十分相符:它是用来重置 HEAD 以及它所指向的 branch 的位置的。
而 reset --hard HEAD^ 之所以起到了撤销 commit 的结果,是由于它把 HEAD 和它所指向的 branch 一起移动到了当前 commit 的父 commit 上,从而起到了「撤销」的结果:

git reset
Git 的历史只能往回看,不能向未来看,所以把 HEAD 和 branch 往回移动,就能起到撤回 commit 的结果。
所以同理,reset --hard 不仅可以撤销提交,还可以用来把 HEAD 和 branch 移动到其他的任何地方。
  1. git reset --hard branch2
复制代码

git reset --hard branch2

reset三种模式区别和使用场景

区别:
使用场景:

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4