我正在寻找一个提交,但不确定使用哪个重置选项。
我当时在看页面,您能否用普通英语解释" git reset"的作用?但是我意识到我并不真正理解git索引或登台区域,因此这些解释无济于事。
另外,--mixed和--soft的用例在该答案中对我来说看起来是相同的(当您要修复并重新提交时。)有人可以进一步分解它吗? 我意识到--mixed可能是可以选择的选项,但是我想知道为什么。 最后,--hard呢?
有人可以给我一个如何选择这三个选项的工作流程示例吗?
-
虐待去编辑我在另一个问题上的答案,以使其更加清晰。
-
@mkarasek的答案非常好,但也有可能对这个问题感兴趣。
-
自我注意:通常,soft: stage everything,mixed: unstage everything,hard: ignore everything直至Im重置之前的提交。
-
另请参阅Bob Kerns对此的其他评论
当您修改存储库中的文件时,更改最初是未暂存的。为了提交它,您必须使用git add对其进行暂存(即,将其添加到索引中)。进行提交时,提交的更改就是已添加到索引的更改。
git reset至少会更改当前分支(HEAD)指向的位置。 --mixed和--soft之间的区别在于您的索引是否也被修改。因此,如果我们在分支master上进行以下一系列提交:
HEAD指向C,并且索引匹配C。
当我们运行git reset --soft B时,master(因此是HEAD)现在指向B,但是索引仍然具有与C相同的更改; git status将按阶段显示它们。因此,如果此时运行git commit,我们将获得一个新提交,其更改与C相同。
好的,所以从这里再次开始:
现在开始git reset --mixed B。 (注意:--mixed是默认选项)。 master和HEAD再次指向B,但是这次也修改了索引以匹配B。如果此时运行git commit,则由于索引匹配HEAD,因此不会发生任何事情。我们仍在工作目录中进行更改,但是由于它们不在索引中,因此git status将它们显示为未暂存。要提交它们,您可以先git add然后照常提交。
最后,--hard与--mixed相同(它更改了HEAD和索引),除了--hard还会修改您的工作目录。如果我们位于C并运行git reset --hard B,则将删除在C中添加的更改以及您所做的所有未提交的更改,并且工作副本中的文件将与提交B相匹配。由于您可以通过这种方式永久丢失更改,因此在执行硬重置之前,应始终运行git status,以确保您的工作目录是干净的,或者可以丢失未提交的更改。
最后是可视化效果:
-
换句话说,--soft放弃最后一次提交,--mix放弃最后一次提交和添加,--hard放弃最后一次提交,添加以及您对代码所做的与git checkout HEAD相同的任何更改
-
一项附加功能:git reset --hard isnt永久,您可以使用reflog恢复更改
-
@eventualEntropy您可以使用reflog恢复所有已提交的更改。用reset --hard删除的未提交的更改将永远消失。
-
如果在reset --mixed之前的工作树中进行本地修改,会发生什么情况?它会覆盖我的本地更改还是将它们合并?
-
@Robert都不; --mixed会更改索引,但不会更改工作目录,因此任何本地修改均不受影响。
-
如果在我的工作副本上还修改了一个重置??ID的文件怎么办?好吧,它们合并了吗? (指混合)
-
对于在终端上使用git并带有颜色的视觉人士可能会有所帮助:1.git reset --soft A,您将看到绿色的B和C(分阶段)2.git reset --mixed A,您将看到B和Cs红色的东西(未暂存)3.git reset --hard A,您将不再在任何地方看到B和C的更改(就好像它们不存在一样)
-
也许值得解释一下,如果您重置了多个提交,将会发生什么。
-
谢谢!让我检查一下我的理解。假设我在这一系列的提交中:-A-B-C(主)我可以在每种情况下期望1.做git reset --mixed B然后做git add然后是git commit使我回到原始状态吗? 2.先做git reset --mixed A,再做git add,再做git commit,这使我回到了原来的情况吗? 3.先执行git reset --soft B然后执行git commit,使我回到原始状态吗? 4.先执行git reset --soft A,然后执行git commit,让我回到原始状态吗?
-
@ user1933930 1和3将留下- A - B - C′,其中C'包含与C相同的更改(具有不同的时间戳和可能的提交消息)。 2和4将留下- A - D,其中D包含B和C的组合更改。
-
git-reset文档
-
@mkarasek(如果您使用Intellij或Jetbrains的其他产品),也可以使用本地历史记录来恢复未提交的代码。这样节省了我的皮肤几次!
-
@mkarasek谢谢,这是一个非常好的和易于理解的答案。
-
如果您有最新的本地和远程仓库,例如修订版C,并且使用--hard还原到版本A,这会还原本地仓库,远程仓库(源)还是同时还原两者?如果只是本地的,一个人如何也偏爱远程起源?即还原最近X次提交的完整步骤清单是什么?
-
@mkarasek,非常感谢您的明确回答:)
-
围绕"阶段"和"索引"的术语使我感到困惑-感谢您澄清它们是同一件事:P
-
我认为您感到困惑和困惑。在下面的@ timhc22s输入下面,我可以在sourcetree中重现它
-
令人愉快的答案!谢谢您的解释!
-
@mkarasek,根据您所写的内容,我很想说以下内容可能是--soft选项的定义:--soft是git reset的选项,因此连续的git commit会导致您进行新的提交与您重置的提交内容相同。我错了吗?
-
次要建议在您的第一个代码块下为" HEAD指向C":HEAD不指向C。它指向master。如果它直接指向C,则您将处于分离状态,而git reset --soft B不会对master产生任何影响。
用最简单的话来说:
-
--soft:取消提交更改,将更改暂存(索引)。
-
--mixed(默认):取消提交+取消暂存更改,更改留在工作树中。
-
--hard:取消提交+取消登台+删除更改,一无所有。
-
最佳答案。 .......
-
最佳答案,因为该答案使用技术术语来提供最简洁的完整答案
-
当我提交了一个文件(未推送)并且我有一个新创建的未跟踪文件时,那么git reset --hard什么都没有?仅当我暂存未跟踪的文件时,它将文件从我的工作目录中删除。
-
错误回答所有3分
-
@Nikhil您能解释这个答案在哪里错误吗?
-
@NedBatchelder一点都不对:因为使用这些命令时,从未提交不会发生。
-
@Nikhil也许您的意思是原始提交仍然存在,这是事实。但是分支已更改,因此提交不再是分支的一部分。我们对此表示同意吗?
-
@NedBatchelder是的,我同意。我要删除我的评论吗?
-
对于初学者:答案既不正确也不正确。这意味着仅对先前的提交进行了重置。但是,您可以将树中的任何提交重置为任何位置。您必须了解reset会移动HEAD和关联的分支指针,并且实际上并不会修改提交树(如" uncommit"所暗示)。但是,出于效率考虑,git将在一段时间(默认为90天)无法访问时(即不在任何分支的历史记录中)删除提交。考虑一下这意味着什么,如果您想继续探索...(还有git prune和gc可能会删除提交)
-
"取消提交"是否意味着"移动头"?这个答案听起来好像上一次提交已被删除,我根本不认为是这种情况。另外,您可以使用RESET从当前HEAD中提取更改,这不会取消任何操作。
-
这是唯一可读的答案。它的准确性:您无法以任何有助于我的日常工作的方式对其进行改进。我不在乎实施琐事。
请注意,这是一个简化的解释,旨在作为寻求了解此复杂功能的第一步。
对于希望通过以下每个命令来形象化其项目状态的视觉学习者可能会有所帮助:
对于那些使用启用了颜色的终端的用户
(git config --global color.ui自动):
git reset --soft A,您将看到B和C的内容为绿色(已暂存并准备提交)
git reset --mixed A(或git reset A),您将看到B和C的内容为红色(未暂存并准备暂存(绿色),然后提交)
git reset --hard A,您将不再在任何地方看到B和C的更改(就好像它们不存在一样)
或对于使用GUI程序(例如" Tower"或" SourceTree")的用户
git reset --soft A,您将在"暂存文件"区域中看到B和C的内容准备提交
git reset --mixed A(或git reset A),您将在"未暂存的文件"区域中看到B和C的内容,准备移至暂存并提交
git reset --hard A,您将不再在任何地方看到B和C的更改(就好像它们不存在一样)
-
这充其量是一种误导,充其量是:您的答案看起来像git reset仅会改变git status的输出外观。
-
我明白您的意思,但是不同意,因为作为一个视觉学习者,使用3个命令后看到我的项目的外观最终帮助我了解了他们在做什么!
-
我看到它更多的是傻瓜式的想法,可以帮助人们缓解实际情况。您能想到如何进行改进以免产生误导吗
-
不,我们不需要更改此答案。它提供了一个方便的"备忘单"。考虑一下:软=绿色,混合=红色,硬=什么都没有(意味着消失)!多么容易记住!对于那些什至不了解这些颜色真正含义的新手,他们对git的了解甚少,无论如何他们将在途中接受艰苦的课程,这不是@unegma的错!顺便说一句,我只是赞成这个答案,以抵消先前的反对。干得好,@ unegma!
-
这是一个很好的补充摘要,可以更好地理解我在其他地方阅读的内部工作原理。谢谢!
-
简洁明了,感谢备忘单! :d
这是TortoiseGit用户的基本说明:
git reset --soft和--mixed保持文件不变。
git reset --hard实际上更改文件以匹配您重置为的提交。
在TortoiseGit中,GUI完全隐藏了索引的概念。修改文件时,不必运行git add即可将更改添加到暂存区/索引。当仅处理不更改文件名的现有文件的修改时,git reset --soft和--mixed是相同的!仅当您添加新文件或重命名文件时,您才会注意到差异。在这种情况下,如果运行git reset --mixed,则必须从"未版本化文件"列表中重新添加文件。
-
关于软和混合的区别,这个答案还不清楚。甚至不屑一顾。下面的答案对此更加清楚。 stackoverflow.com/questions/2530060/
-
作为也具有相同行为的Github Desktop用户,此答案使我更加清楚为什么我对--mixed和--soft感到困惑。
在这些情况下,我喜欢可以希望对此进行解释的视觉效果:
git reset --[hard/mixed/soft]:
所以每个影响不同的范围
困难=> WorkingDir +索引+ HEAD
混合=>索引+ HEAD
软=>仅HEAD(索引和工作目录不变)。
所有其他答案都很不错,但我发现最好将文件分为三类来理解它们:unstaged,staged,commit:
-
--hard应该易于理解,它可以还原所有内容
-
--mixed(默认):
-
unstaged文件:请勿更改
-
staged文件:移至unstaged
-
commit文件:移至unstaged
-
--soft:
-
unstaged文件:请勿更改
-
staged文件:请勿更改
-
commit文件:移至staged
综上所述:
-
--soft选项会将所有内容(unstaged文件除外)移到staging area
-
--mixed选项会将所有内容移至unstaged area
在进入这三个选项之前,必须先了解三件事。
1)历史/ HEAD
2)阶段/索引
3)工作目录
reset --soft:历史记录已更改,HEAD已更改,工作目录未更改。
reset --mixed:历史记录已更改,HEAD已更改,工作目录已更改,但未暂存数据。
reset --hard:历史记录已更改,HEAD已更改,工作目录已更改,丢失了数据。
使用Git --soft始终是安全的。一个人应该在复杂的需求中使用其他选项。
您不必强迫自己记住它们之间的差异。考虑一下您实际上是如何提交的。
1.进行一些更改。
2.git添加
3.gc -m"我做了什么"
软,混合和硬是您可以放弃从3到1进行的操作的方式。
软"假装"到永远不会看到您做了" gc -m"。
混成"假装",以至于从未见过" git add"。
很难"假装"永远不会看到您进行了文件更改。
这里有许多关于git reset --soft的误解。在特定情况下,git reset --soft仅会更改HEAD(从分离的磁头状态开始),通常(并用于预期用途),它会移动您当前已签出的分支引用。当然,如果您没有签出分支,则无法执行此操作(因此,git reset --soft仅会更改HEAD的特定条件)。
我发现这是思考git reset的最佳方法。您不仅在移动HEAD(所有操作都在做),还在移动分支引用,例如master。这与运行git commit(当前分支与HEAD一起移动)时发生的情况类似,除了移动(而不是创建(移至)新的提交,而是移至上一个提交)。
这是reset的要点,将分支更改为新提交以外的其他内容,而不更改HEAD。您可以在文档示例中看到以下内容:
Undo a commit, making it a topic branch
1 2 3
| $ git branch topic/wip (1)
$ git reset --hard HEAD~3 (2)
$ git checkout topic/wip (3) |
You have made some commits, but realize they were premature to be in the"master" branch. You want to continue polishing them in a topic branch, so create"topic/wip" branch off of the current HEAD.
Rewind the master branch to get rid of those three commits.
Switch to"topic/wip" branch and keep working.
这一系列命令的意义是什么?您想移动一个分支,这里是master,因此当您签出master时,您将运行git reset。
在这里,票数最高的答案通常是好的,但我想我会添加它以纠正一些带有误解的答案。
更改您的分支
git reset --soft :将当前检出的分支的分支指针重置为指定参考处的提交。您的工作目录和索引中的文件不会更改。从这个阶段提交将使您回到git reset命令之前的状态。
也更改您的索引
git reset --mixed
或同等
git reset :
--soft所做的与,并且还将索引重置为与指定参考上的提交匹配的索引。尽管git reset --soft HEAD不执行任何操作(因为它说将已检出的分支移至已检出的分支),但git reset --mixed HEAD或等效的git reset HEAD是常见且有用的命令,因为它将索引重置为上一次提交的状态。
也更改您的工作目录
git reset --hard :执行--mixed的操作,并且还覆盖您的工作目录。该命令类似于git checkout ,除了(这是关于reset的关键点)所有形式的git reset移动分支引用HEAD所指向。
关于"这样的命令移动HEAD"的注释:
说命令移动HEAD是没有用的。任何更改提交历史记录中位置的命令都会移动HEAD。这就是HEAD的含义,它是指向您所在位置的指针。 HEAD是您,因此您每次行动都会移动。
-
"移动分支引用":好点。我必须更新stackoverflow.com/a/5203843/6309。
--soft:告诉Git将HEAD重置为另一个提交,因此索引和工作目录不会以任何方式更改。在原始HEAD和提交之间更改的所有文件都将被暂存。
--mixed:就像软件一样,这会将HEAD重置为另一个提交。它还将重置索引以使其匹配,而不会触摸工作目录。所有更改都将保留在工作目录中,并显示为已修改但未上演。
--hard:这将重置所有内容-将HEAD重置为另一个提交,重置索引以使其匹配,并重置工作目录以使其也匹配。
--mixed和--soft之间的主要区别是您的索引是否也被修改。在此处查看有关此内容的更多信息。
git reset命令的各个选项之间的基本区别如下。
-
--soft:仅将HEAD重置为您选择的提交。基本上与git checkout相同,但不会创建分离的头部状态。
-
--mixed(默认选项):将HEAD重置为您在历史记录中选择的提交,并撤消索引中的更改。
-
--hard:将HEAD重置为您在两个历史记录中选择的提交,撤消索引中的更改,并撤消工作目录中的更改。
在什么情况下使用3个选项的简短答案:
要在代码中保留当前更改,但要重写提交历史记录,请执行以下操作:
-
soft:您可以一次提交所有内容,并使用新的描述创建一个新的提交(如果使用torotise git或任何其他大多数GUI,则可以使用它,因为您仍然可以在提交中勾选想要的文件并使用不同的文件进行多次提交。在Sourcetree中,所有文件都将被暂存以进行提交。)
-
mixed:提交提交之前,必须将各个文件再次添加到索引中(在Sourcetree中,所有更改的文件都将被取消登台)
要实际上也丢失代码中的更改:
-
hard:您不仅会重写历史记录,而且还会丢失所有更改,直到重置为止
-
在这种情况下,我不会变得柔和而混杂。如果您必须提交,那么恢复了什么?您是要提交还原还是要提交更改(以便恢复到原始状态?)
-
重新提交更改。不会有反向提交。
mkarasek的答案很棒,简单来说,我们可以说...
-
git reset --soft:将HEAD设置为预期的提交,但保持更改从上一次提交开始
-
git reset --mixed:与git reset --soft相同,但唯一的不同是它取消了上一次提交的更改
-
git reset --hard:在您指定的提交上设置您的HEAD,并从上次提交中重置所有更改,包括未提交的更改。