如何以及何时使用 Git Reset
我们大多数人都会避免使用可怕的 git reset 命令——但实际上它真的很有用,只要你知道它是如何工作的!
git reset 起什么作用?
简单来说,git reset 会将你的分支带回到提交历史中的某个点,但这有三个不同的级别:
- soft:将头部移回到指定的提交,但将所有更新的文件保留在索引和工作目录中 -您移动到的提交之后的所有文件都已被跟踪(如执行 git add)并准备作为新提交提交。
- 混合:将文件头和文件索引移回指定的提交,但保留工作目录中的文件——提交后的所有文件都将作为未跟踪文件保留在工作目录中。如果您现在将它们全部添加,则将处于与上述软重置相同的阶段。
- hard:将头部、索引和工作目录移回到指定的提交处 — —指定提交后的所有更新文件现在都 *消失了* !!!(此时未提交的文件无法恢复)
你为什么需要这个?
这里有几个例子,能让你更好地了解何时使用它们。你应该只在自己的分支上执行此操作,或者在你确定没有人已经拉取过你将要移除的提交时执行此操作。
柔软的
假设您已经做了一些小的提交,并且希望将它们全部放入 1 个更具描述性的提交中。
A->B->C->D
git reset — soft A
你的分支头现在指向 A
git commit -m “my new merged commit”
git push origin branch --force-with-lease
我们现在有了一个新的提交 E,但它包含了在 B、C、D 中提交的所有文件。注意:强制使用租约标志是因为否则 git 会报错,说你的本地分支落后于远程分支。(这是强制的更安全版本)
A->E
混合
您刚刚推送了几个提交,但您想返回并删除前一次提交中的几个文件。
A->B->C
git reset --mixed A
您的分支头和索引指向 A
git status
这将显示 B 和 C 中的所有更改都存在,但未被跟踪
现在你可以自由地将想要添加的文件添加到新的提交中
git add <files> git commit -m "updated commit"
git push origin branch --force-with-lease
A->D
您的头脑现在位于新的提交 D,并且您尚未暂存的任何文件仍将位于您的工作树中,准备添加到另一个提交或执行您想要的操作。
难的
你什么时候可能会需要这个?通常是在事情出错的时候,因为风险非常大。我会给你讲一个我曾经需要它的场景。
我一直在自己的分支上工作,测试一个功能,并且我已经更改了许多文件,但它失败了,我想返回一些提交并摆脱从那时起所做的所有更改。
如果我没有做过任何提交,也没有推送过任何提交,我可以直接重置回提交 A,这样我的工作目录就清空了,我所有更新的文件都会从历史记录中消失。
git reset --hard A
如果我已经将这些提交推送到远程分支,那么在执行此操作之前,您需要确保没有人正在使用这些提交,因为它们将被孤立。但是,如果您确定这样做是安全的,那么请运行上面的命令。唯一的区别是,您需要在之后执行强制推送才能将远程分支推送到该状态,否则它会告诉您本地分支已落后。
git reset --hard A
git push origin branchname --force-with-lease
这将从远程分支历史记录中删除您的提交,因此您会发现这可能非常危险。
最近我用这个方法摆脱了合并提交回滚的困境。我发起了一个拉取请求,想把一个分支合并到另一个分支,结果出现了合并冲突,而且这些冲突没有得到正确解决,所以我回滚了合并。然而,这意味着我无法再次发起拉取请求,因为它没有更新,所以我尝试回滚,结果却弄得一团糟。之后,我使用 git reset --hard 将分支恢复到出现这种情况之前的状态,并清除了历史记录中这些糟糕的回滚!