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

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

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

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

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


当前回答

记住在git中你有:

HEAD指针,它告诉你你在做什么提交 工作树,它表示系统上文件的状态 暂存区(也称为索引),它“暂存”更改,以便稍后可以一起提交

请详细说明: ——硬,——软,——融合;

按危险程度递增:

-轻轻移动头部,但不触及集结区或工作树。 mixed移动HEAD并更新暂存区,但不更新工作树。 ——merge移动HEAD,重置暂存区域,并尝试将工作树中的所有更改移动到新的工作树中。 -hard移动HEAD,调整你的集结区和工作树到新的HEAD,扔掉所有东西。

具体的用例和工作流;

当你想要转移到另一个地方,修补事情而不“失去你的位置”时,使用-软。你很少需要这个。

--

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

--

当您想要查看另一次提交时的情况,但又不想丢失已有的任何更改时,请使用——mixed(这是默认值)。 使用—合并当你想移动到一个新的点,但合并你已经有到工作树的变化。 使用——在新的提交时很难清除所有内容并重新开始。

其他回答

我不总是做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

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

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

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

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

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

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

记住在git中你有:

HEAD指针,它告诉你你在做什么提交 工作树,它表示系统上文件的状态 暂存区(也称为索引),它“暂存”更改,以便稍后可以一起提交

请详细说明: ——硬,——软,——融合;

按危险程度递增:

-轻轻移动头部,但不触及集结区或工作树。 mixed移动HEAD并更新暂存区,但不更新工作树。 ——merge移动HEAD,重置暂存区域,并尝试将工作树中的所有更改移动到新的工作树中。 -hard移动HEAD,调整你的集结区和工作树到新的HEAD,扔掉所有东西。

具体的用例和工作流;

当你想要转移到另一个地方,修补事情而不“失去你的位置”时,使用-软。你很少需要这个。

--

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

--

当您想要查看另一次提交时的情况,但又不想丢失已有的任何更改时,请使用——mixed(这是默认值)。 使用—合并当你想移动到一个新的点,但合并你已经有到工作树的变化。 使用——在新的提交时很难清除所有内容并重新开始。