我看过一些有趣的帖子,解释git重置的微妙之处。

不幸的是,我读得越多,就越觉得我并没有完全理解它。我有SVN的背景,Git是一个全新的范例。我很容易得到mercurial,但是Git的技术含量更高。

我认为git重置接近hg恢复,但似乎有区别。

git重置到底是做什么的?请详细说明:

选项——硬、软和合并; 你对HEAD使用的奇怪符号,如HEAD^和HEAD~1; 具体的用例和工作流程; 对工作副本、HEAD和整体压力水平的影响。


当前回答

我不总是做git重置,但当我这样做时,我看到这个:

* 444668f (HEAD -> main) C
|
* c3739b7 B
|
* 207e8a1 A
|
* 38fab46 Initial commit


git reset --hard 207e8


* 207e8a1 (HEAD -> main) A
|
* 38fab46 Initial commit


To retrieve the changes, use --soft instead

HEAD移到A (main也是,因为HEAD指向main)。git reset不会“重置”B和C。你仍然可以使用git log的——reflog选项看到B和C:

git log --graph --oneline --all --reflog

警告

在你做git重置之前,

如果你有非阶段性的变化: 如果用力,就会被丢弃 使用——mixed(默认),它将与阶段性更改混合,检索到的更改将提交更改 如果你有阶段性的变化: 如果用力,就会被丢弃 使用——mixed,它将与非阶段更改和检索到的提交更改混合 使用——soft,它将与检索到的提交更改混合在一起

要摆脱它们,你可以使用git stash,但我更喜欢只创建一个新分支,并为那里的阶段性和非阶段性更改创建一个单独的提交。然后使用git rebase + git重置当我需要他们回来。

其他回答

博客Pro Git中的Reset Demystified给出了一个关于Git重置和Git checkout的非常简单的解释。

在那篇文章的顶部进行了有益的讨论之后,作者将这些规则简化为以下简单的三步:

基本上就是这样。reset命令以特定顺序覆盖这三棵树,当您命令它停止时停止。 移动HEAD指向的分支(如果—软) 然后,让索引看起来像这样(停止在这里,除非——很难) 然后,让工作目录看起来像这样 还有“合并”和“保留”选项,但我现在宁愿让事情简单一些——这将是另一篇文章。

请注意,这是一个简化的解释,旨在作为寻求理解这个复杂功能的第一步。

对于那些想要在这些命令之后可视化他们的项目状态的视觉学习者来说,这可能是有帮助的:


适用于开启彩色终端机的用户 (git配置——global color。ui汽车):

git重置-软A,你会看到B和C的东西在绿色(分期和准备提交)

git重置-混合A(或git重置A),你会看到B和C的东西在红色(未分期和准备分期(绿色),然后提交)

git重置-硬A,你将不再看到B和C的变化在任何地方(将好像他们从来没有存在过)


或者对于那些使用像“塔”或“SourceTree”这样的GUI程序的人

git重置——软A,你会看到B和C的东西在“阶段性文件”区域准备提交

git reset—混合A(或git reset A),你会看到B和C的东西在“unstaging files”区域准备移动到staging,然后提交

git重置-硬A,你将不再看到B和C的变化在任何地方(将好像他们从来没有存在过)

我不总是做git重置,但当我这样做时,我看到这个:

* 444668f (HEAD -> main) C
|
* c3739b7 B
|
* 207e8a1 A
|
* 38fab46 Initial commit


git reset --hard 207e8


* 207e8a1 (HEAD -> main) A
|
* 38fab46 Initial commit


To retrieve the changes, use --soft instead

HEAD移到A (main也是,因为HEAD指向main)。git reset不会“重置”B和C。你仍然可以使用git log的——reflog选项看到B和C:

git log --graph --oneline --all --reflog

警告

在你做git重置之前,

如果你有非阶段性的变化: 如果用力,就会被丢弃 使用——mixed(默认),它将与阶段性更改混合,检索到的更改将提交更改 如果你有阶段性的变化: 如果用力,就会被丢弃 使用——mixed,它将与非阶段更改和检索到的提交更改混合 使用——soft,它将与检索到的提交更改混合在一起

要摆脱它们,你可以使用git stash,但我更喜欢只创建一个新分支,并为那里的阶段性和非阶段性更改创建一个单独的提交。然后使用git rebase + git重置当我需要他们回来。

博士TL;

git reset重置Staging到最后一次提交。使用——很难将工作目录中的文件重置到最后一次提交。

完整版

但这显然过于简单,因此会有许多相当啰嗦的答案。对我来说,在撤销更改的上下文中阅读git重置更有意义。请看这个:

如果git恢复是一种“安全”的方法来撤销更改,您可以考虑git 复位为危险方法。当你撤销与git重置(和 提交不再被任何ref或reflog引用),有 无法检索原始副本—这是永久撤销。护理必须 在使用这个工具的时候,你可能会遇到这样的问题,因为它是唯一一个有可能丢失你的工作的Git命令。

从https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

在提交级别,重置是一种将分支的尖端移动到不同提交的方法。这可用于从当前分支删除提交。

从https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations

签出将头部指向特定的提交。

重置在特定提交时指向一个分支。(分支是指向提交的指针。)

顺便说一句,如果你的头没有指向分支也指向的提交,那么你就有了一个分离的头。(结果证明是错的。看到评论…)