In plain English, what does “git reset” do?
我看过一些有趣的文章,解释了关于
不幸的是,我读到的越多,我就越不完全理解它。我来自SVN背景,而Git是一个全新的范例。我很容易变化无常,但Git更具技术性。
我认为
那么,
- 期权
--hard 、--soft 和--merge ; - 与
HEAD 一起使用的奇怪符号,如HEAD^ 和HEAD~1 ; - 具体用例和工作流程;
- 对工作副本、
HEAD 和全球压力水平的影响。
一般来说,
1 | - A - B - C (HEAD, master) |
你意识到你想让大师指向b而不是c,你会用
1 | - A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore |
号
题外话:这和结账不同。如果你运行
1 | - A - B (HEAD) - C (master) |
你最终进入了一种超然的状态。
1 2 3 | - A - B - C (master) \ D (HEAD) |
。
记住,reset不进行提交,它只是更新一个分支(指向提交的指针)以指向不同的提交。剩下的只是您的索引和工作树发生了什么的细节。好的。用例
我在下一节中对各种选项的描述中介绍了
--hard 会使你真正失去工作。它会修改您的工作树。好的。git reset [options] commit 会使你(某种程度上)失去承诺。在上面的玩具示例中,我们丢失了commitC 。它仍在回购中,您可以通过查看git reflog show HEAD 或git reflog show master 找到它,但实际上它不再可以从任何分支访问。好的。Git会在30天后永久删除这类承诺,但在此之前,您可以通过再次指向它的分支来恢复C(
git checkout C; git branch )。好的。
论据
套用手册页,最常见的用法是
例如,
有四个主要选项来控制重置期间工作树和索引的情况。好的。
记住,索引是Git的"准备区"——当你准备提交时说
--hard 使所有内容都与您重置的提交相匹配。这可能是最容易理解的。你所有的地方性变化都会受到打击。一个主要的用途是吹走你的工作,但不是交换承诺:git reset --hard 意味着git reset --hard HEAD ,也就是说,不要改变分支,而是消除所有的局部变化。另一种方法是将分支从一个地方移动到另一个地方,并保持索引/工作树的同步。这真的会让你失去工作,因为它会修改你的工作树。在运行任何reset --hard 之前,一定要扔掉本地工作。好的。--mixed 为违约,即git reset 表示git reset --mixed 。它重置索引,但不重置工作树。这意味着所有文件都是完整的,但是原始提交和重置为的文件之间的任何差异都将显示为具有git状态的本地修改(或未跟踪文件)。当你意识到你做了一些糟糕的承诺,但你想保留你所做的所有工作,这样你就可以修复它并重新提交。为了提交,您必须再次向索引添加文件(git add ... )。好的。--soft 不接触索引或工作树。您的所有文件与--mixed 一样完整,但所有更改显示为带有git状态的changes to be committed (即已签入以准备提交)。当你意识到你做了一些不好的承诺,但工作都是好的-你需要做的就是以不同的方式重新承诺。索引未被修改,因此如果需要,可以立即提交-结果提交将具有与重置前相同的内容。好的。最近增加了
--merge ,旨在帮助您中止失败的合并。这是必要的,因为git merge 实际上允许您尝试与脏的工作树(一个带有本地修改的工作树)合并,只要这些修改位于不受合并影响的文件中。git reset --merge 重置索引(如--mixed ——所有更改都显示为本地修改),并重置受合并影响的文件,但只保留其他文件。希望这能使一切恢复到糟糕合并之前的状态。您通常将它用作git reset --merge (意味着git reset --merge HEAD ),因为您只想重置合并,而不是实际移动分支。(由于合并失败,HEAD 尚未更新)好的。更具体地说,假设您修改了文件A和B,并尝试在修改了文件C和D的分支中合并。由于某种原因合并失败,您决定中止合并。你用的是
git reset --merge 。它使C和D回到了它们在HEAD 中的状态,但只剩下对A和B的修改,因为它们不是试图合并的一部分。好的。
想知道更多吗?
我确实认为
您提到的"奇怪的符号"(
HEAD~ 是HEAD~1 的缩写,表示commit的第一个父代。HEAD~2 表示承诺的第一个母公司的第一个母公司。把HEAD~n 看作是"头前的N承诺"或"头的第n代祖先"。HEAD^ 或HEAD^1 也指承诺的第一个母公司。HEAD^2 表示承诺的第二方母公司。记住,正常的合并提交有两个父级——第一个父级是合并到提交中的,第二个父级是合并后的提交。一般来说,合并可以有任意多个父母(章鱼合并)。^ 和~ 操作符可以串在一起,如HEAD~3^2 中,HEAD 第三代祖先的第二代父代、HEAD^^2 中,HEAD 第一代父代的第二代父代,甚至HEAD^^^ 中,相当于HEAD~3 。
。好的。好啊。
记住,在
HEAD 指针,它告诉您正在处理什么提交。- 工作树,表示系统上文件的状态
- 临时区域(也称为索引),它会更改"阶段",以便以后可以一起提交。
Please include detailed explanations about:
--hard ,--soft and--merge ;
号
危险性的增加顺序:
--soft 移动HEAD ,但不接触集结区或工作树。--mixed 移动HEAD 并更新临时区域,但不更新工作树。--merge 移动HEAD ,重置临时区域,并尝试将工作树中的所有更改移动到新的工作树中。--hard 移动HEAD ,调整你的集结地和工作树到新的HEAD ,扔掉所有东西。
concrete use cases and workflows;
号
- 当你想转移到另一个任务中去,在不"失去你的位置"的情况下,使用
--soft 。你很少需要这个。
——
1 2 3 4 5 6 | # 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 (这是默认设置),但您不想丢失已经有的任何更改。当您想要移动到一个新地点,但将您已经有的更改合并到工作树中时,可以使用
--merge 。使用
--hard 清除所有内容,并在新的提交时重新开始。
在博客pro-git中,重置后的数据对
在文章顶部进行了所有有益的讨论之后,作者将规则简化为以下简单的三个步骤:
That is basically it. The
reset command overwrites these three trees in a specific order, stopping when you tell it to.Move whatever branch HEAD points to (stop if --soft )THEN, make the Index look like that (stop here unless --hard )THEN, make the Working Directory look like that There are also
--merge and--keep options, but I would rather keep things simpler for now - that will be for another article.
号
当你向Git提交一些东西时,你首先必须准备(添加到索引中)你的更改。这意味着您必须在Git将其视为提交的一部分之前,Git添加您希望包含在此提交中的所有文件。让我们先看看Git回购的图像:。
所以,现在很简单。我们必须在工作目录中工作,创建文件、目录等等。这些更改是未跟踪的更改。要使它们被跟踪,我们需要使用git add命令将它们添加到git索引中。一旦它们被添加到Git索引中。我们现在可以提交这些更改,如果我们想将其推送到Git存储库。
但是突然间我们知道了,在提交我们有一个额外的文件,我们在索引中添加了这个文件,不需要在Git存储库中进行推送。这意味着我们不希望该文件出现在索引中。现在的问题是如何从git索引中删除该文件,因为我们使用git add将其放入索引中,所以使用git rm是合乎逻辑的?错了!git rm只需删除文件并将删除内容添加到索引中。那么现在该怎么做:
用途:
git reset
号
它会清除您的索引,使您的工作目录保持不变。(简单地把所有东西都拆开)。
它可以与许多选项一起使用。Git Reset有三个主要选项可供使用:--硬、--软和--混合。当你重置时,除了头部指针之外,这些都会影响get的重置。
首先,硬重置一切。您当前的目录将与您一直跟踪该分支时的目录完全相同。工作目录和索引将更改为该提交。这是我最常使用的版本。git reset——hard类似于svn revert。
接下来,完全相反的-soft不会重置工作树或索引。它只移动头部指针。这将使您的当前状态中的任何更改都不同于您要在目录中就地切换到的提交,并"分段"进行提交。如果您在本地提交,但没有将提交推送到Git服务器,则可以重置为上一次提交,并使用良好的提交消息重新提交。
最后,—mixed重置索引,但不重置工作树。所以这些更改仍然存在,但是是"未分页的",需要git-add ed或git-commit-a。如果我们提交的内容超过了git-commit-a的预期,我们有时会使用这个方法,我们可以使用git-reset退出commit-mixed,添加我们想要提交的内容,只需提交东南方。
Git Revert和Git Reset之间的差异:
简单来说,git reset是一个"修复未提交错误"的命令,而git revert是一个"修复已提交错误"的命令。
这意味着,如果我们在某些更改中犯了一些错误,并将其提交并推送到Git repo,那么Git Revert就是解决方案。如果我们在推送/提交之前发现了相同的错误,我们可以使用git reset来解决问题。
我希望它能帮助你摆脱困惑。
DR
git reset resets Staging to the last commit. Use--hard to also reset files in your Working directory to the last commit.
号
较长版本
但这显然是简单化的,因此有许多相当冗长的答案。对于我来说,在撤销变更的背景下阅读
If git revert is a"safe" way to undo changes, you can think of git
reset as the dangerous method. When you undo with git reset(and the
commits are no longer referenced by any ref or the reflog), there is
no way to retrieve the original copy—it is a permanent undo. Care must
be taken when using this tool, as it’s one of the only Git commands that has the potential to lose your work.
号
来自https://www.atlassian.com/git/tutorials/undong-changes/git-reset
还有这个
On the commit-level, resetting is a way to move the tip of a branch to a different commit. This can be used to remove commits from the current branch.
号
来自https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations
请注意,这是一个简化的解释,旨在作为理解这一复杂功能的第一步。
对于希望在每个命令之后可视化项目状态的视觉学习者来说,这可能会有所帮助:
对于那些使用已打开颜色的终端的用户(git config--global color.ui auto):
你再也看不到B和C的变化了(就好像它们从未存在过一样)。
或者对于那些使用类似"tower"或"sourcetree"的GUI程序的用户
EDOCX1(或EDOCX1(或EDOCX1)(2)),您将在"未归档文件"区域中看到b和c的内容,准备转移到阶段,然后提交
你再也看不到B和C的变化了(就好像它们从未存在过一样)。
签出将头部指向特定的提交。
重置将分支指向特定的提交。(分支是指向提交的指针。)
顺便说一句,如果你的头没有指向一个分支也指向的提交,那么你有一个分离的头。(原来是错的。请参见注释…)