git reset --mixed、--soft 和 --hard 之间有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3528245/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between git reset --mixed, --soft, and --hard?
提问by Michael Chinen
I'm looking to split a commit up and not sure which reset option to use.
我希望拆分一次提交,但不确定要使用哪个重置选项。
I was looking at the page In plain English, what does "git reset" do?, but I realized I don't really understand what the git index or staging area is and thus the explanations didn't help.
我正在查看页面用简单的英语,“git reset”有什么作用?,但我意识到我并不真正理解 git 索引或暂存区是什么,因此解释没有帮助。
Also, the use cases for --mixed
and --soft
look the same to me in that answer (when you want to fix and recommit). Can someone break it down even more? I realize --mixed
is probably the option to go with, but I want to know why. Lastly, what about --hard
?
此外,在该答案中(当您想要修复和重新提交时)的用例--mixed
和--soft
我看起来相同。有人可以进一步分解吗?我意识到--mixed
可能是一个选择,但我想知道为什么。最后--hard
呢?
Can someone give me a workflow example of how selecting the 3 options would happen?
有人可以给我一个工作流程示例,说明如何选择 3 个选项?
回答by mkarasek
When you modify a file in your repository, the change is initially unstaged. In order to commit it, you must stage it—that is, add it to the index—using git add
. When you make a commit, the changes that are committed are those that have been added to the index.
当您修改存储库中的文件时,更改最初是未暂存的。为了提交它,您必须使用git add
. 进行提交时,提交的更改是已添加到索引中的更改。
git reset
changes, at minimum, where the current branch (HEAD
) is pointing. The difference between --mixed
and --soft
is whether or not your index is also modified. So, if we're on branch master
with this series of commits:
git reset
至少会更改当前分支 ( HEAD
) 指向的位置。--mixed
和之间的区别在于--soft
您的索引是否也被修改。所以,如果我们在master
这一系列提交的分支上:
- A - B - C (master)
HEAD
points to C
and the index matches C
.
HEAD
指向C
并且索引匹配C
。
When we run git reset --soft B
, master
(and thus HEAD
) now points to B
, but the index still has the changes from C
; git status
will show them as staged. So if we run git commit
at this point, we'll get a new commit with the same changes as C
.
当我们运行时git reset --soft B
,master
(因此HEAD
)现在指向B
,但索引仍然有从C
;开始的变化。git status
将它们显示为已上演。因此,如果我们此时运行git commit
,我们将获得与C
.
Okay, so starting from here again:
好的,所以从这里重新开始:
- A - B - C (master)
Now let's do git reset --mixed B
. (Note: --mixed
is the default option). Once again, master
and HEAD
point to B, but this time the index is also modified to match B
. If we run git commit
at this point, nothing will happen since the index matches HEAD
. We still have the changes in the working directory, but since they're not in the index, git status
shows them as unstaged. To commit them, you would git add
and then commit as usual.
现在让我们做git reset --mixed B
。(注意:--mixed
是默认选项)。再一次,master
并HEAD
点到B,但这次的指数也被修改,以匹配B
。如果我们此时运行git commit
,则不会发生任何事情,因为索引匹配HEAD
。我们仍然在工作目录中进行了更改,但由于它们不在索引中,因此将git status
它们显示为未暂存。要提交它们,您将git add
像往常一样提交。
And finally, --hard
is the same as --mixed
(it changes your HEAD
and index), except that --hard
also modifies your working directory. If we're at C
and run git reset --hard B
, then the changes added in C
, as well as any uncommitted changes you have, will be removed, and the files in your working copy will match commit B
. Since you can permanently lose changes this way, you should always run git status
before doing a hard reset to make sure your working directory is clean or that you're okay with losing your uncommitted changes.
最后,--hard
与--mixed
(它更改您的HEAD
和索引)相同,除了它--hard
还会修改您的工作目录。如果我们在C
并运行git reset --hard B
,那么添加的更改C
以及您拥有的任何未提交的更改都将被删除,并且您的工作副本中的文件将匹配 commit B
。由于您可以通过这种方式永久丢失更改,因此您应该始终git status
在进行硬重置之前运行,以确保您的工作目录是干净的,或者您可以丢失未提交的更改。
And finally, a visualization:
最后,一个可视化:
回答by Mo Ali
In the simplest terms:
用最简单的话来说:
--soft
: uncommitchanges, changes are left staged (index).--mixed
(default): uncommit + unstagechanges, changes are left in working tree.--hard
: uncommit + unstage + deletechanges, nothing left.
--soft
:取消提交更改,更改被保留(index)。--mixed
(默认):取消提交 + 取消暂存更改,更改保留在工作树中。--hard
:取消提交 + 取消暂存 + 删除更改,什么都不剩。
回答by timhc22
Please be aware, this is a simplified explanation intended as a first step in seeking to understand this complex functionality.
请注意,这是一个简化的解释,旨在作为寻求理解这一复杂功能的第一步。
May be helpful for visual learners who want to visualise what their project state looks like after each of these commands:
对于想要在每个命令后可视化项目状态的视觉学习者可能会有所帮助:
For those who use Terminal with colour turned on (git config --global color.ui auto):
对于那些在颜色打开的情况下使用终端的人(git config --global color.ui auto):
git reset --soft A
and you will see B and C's stuff in green (staged and ready to commit)
git reset --soft A
你会看到 B 和 C 的东西呈绿色(已上演并准备提交)
git reset --mixed A
(or git reset A
) and you will see B and C's stuff in red (unstaged and ready to be staged (green) and then committed)
git reset --mixed A
(或git reset A
),您将看到 B 和 C 的内容为红色(未暂存并准备暂存(绿色)然后提交)
git reset --hard A
and you will no longer see B and C's changes anywhere (will be as if they never existed)
git reset --hard A
并且您将不再在任何地方看到 B 和 C 的变化(就像它们从未存在过一样)
Or for those who use a GUI program like 'Tower' or 'SourceTree'
或者对于那些使用像“Tower”或“SourceTree”这样的 GUI 程序的人
git reset --soft A
and you will see B and C's stuff in the 'staged files' area ready to commit
git reset --soft A
你会在“暂存文件”区域看到 B 和 C 的东西准备提交
git reset --mixed A
(or git reset A
) and you will see B and C's stuff in the 'unstaged files' area ready to be moved to staged and then committed
git reset --mixed A
(或git reset A
),您将在“未暂存文件”区域中看到 B 和 C 的内容准备移至暂存然后提交
git reset --hard A
and you will no longer see B and C's changes anywhere (will be as if they never existed)
git reset --hard A
并且您将不再在任何地方看到 B 和 C 的变化(就像它们从未存在过一样)
回答by Hansen W
All the other answers are great, but I find it best to understand them by breaking down files into three categories: unstaged
, staged
, commit
:
所有其他答案都很棒,但我发现最好通过将文件分为三类来理解它们:unstaged
、staged
、commit
:
--hard
should be easy to understand, it restores everything--mixed
(default):unstaged
files: don't changestaged
files: move tounstaged
commit
files: move tounstaged
--soft
:unstaged
files: don't changestaged
files: dont' changecommit
files: move tostaged
--hard
应该很容易理解,它恢复了一切--mixed
(默认):unstaged
文件:不要改变staged
文件:移至unstaged
commit
文件:移至unstaged
--soft
:unstaged
文件:不要改变staged
文件:不要改变commit
文件:移至staged
In summary:
总之:
--soft
option will move everything (exceptunstaged
files) intostaging area
--mixed
option will move everything intounstaged area
--soft
选项会将所有内容(unstaged
文件除外)移动到staging area
--mixed
选项会将所有内容移动到unstaged area
回答by James Lawruk
Here is a basic explanation for TortoiseGit users:
以下是 TortoiseGit 用户的基本解释:
git reset --soft
and --mixed
leave your files untouched.
git reset --soft
并--mixed
保持您的文件不变。
git reset --hard
actually change your filesto match the commit you reset to.
git reset --hard
实际上更改您的文件以匹配您重置的提交。
In TortoiseGit, The concept of the indexis very hidden by the GUI. When you modify a file, you don't have to run git add
to add the change to the staging area/index. When simply dealing with modifications to existing files that are not changing file names, git reset --soft
and --mixed
are the same! You will only notice a difference if you added new files or renamed files. In this case, if you run git reset --mixed, you will have to re-add your file(s) from the Not Versioned Fileslist.
在 TortoiseGit 中,索引的概念被 GUI 隐藏得很深。修改文件时,您不必运行git add
将更改添加到暂存区/索引。当只是处理对现有文件的修改时,不会更改文件名,git reset --soft
并且--mixed
是相同的!如果您添加新文件或重命名文件,您只会注意到差异。在这种情况下,如果您运行 git reset --mixed,您将不得不从Not Versioned Files列表中重新添加您的文件。
回答by Tomer Ben David
In these cases I like a visual that can hopefully explain this:
在这些情况下,我喜欢可以解释这一点的视觉效果:
git reset --[hard/mixed/soft]
:
git reset --[hard/mixed/soft]
:
So each effect different scopes
所以每个效果不同的范围
- Hard => WorkingDir + Index + HEAD
- Mixed => Index + HEAD
- Soft => HEAD only (index and working dir unchanged).
- 硬 => WorkingDir + 索引 + HEAD
- 混合 => 索引 + HEAD
- Soft => HEAD only(索引和工作目录不变)。
回答by matt
Three types of regret
三种后悔
A lot of the existing answers don't seem to answer the actual question. They are about what the commands do, not about what you (the user) want — the use case. But that is what the OP asked about!
许多现有答案似乎并没有回答实际问题。它们是关于命令的作用,而不是关于你(用户)想要什么——用例。但这就是OP所问的!
It might be more helpful to couch the description in terms of what it is precisely that you regretat the time you give a git reset
command. Let's say we have this:
根据您在下达命令时后悔的事情来进行描述可能会更有帮助git reset
。假设我们有这个:
A - B - C - D <- HEAD
Here are some possible regrets and what to do about them:
以下是一些可能的遗憾以及如何处理它们:
1. I regret that B, C, and D are not onecommit.
1. 我很遗憾 B、C 和 D 不是一个提交。
git reset --soft A
. I can now immediately commit and presto, all the changes since A areone commit.
git reset --soft A
. 我现在可以立即提交并快速提交,自 A 以来的所有更改都是一次提交。
2. I regret that B, C, and D are not tencommits.
2. 我很遗憾 B、C 和 D 不是十次提交。
git reset --mixed A
. The commits are gone and the index is back at A, but the work area still looks as it did after D. So now I can add-and-commit in a whole different grouping.
git reset --mixed A
. 提交消失了,索引又回到了 A,但工作区看起来仍然和 D 之后一样。所以现在我可以在一个完全不同的分组中添加和提交。
3. I regret that B, C, and D happened on this branch; I wish I had branched after A and they had happened on that other branch.
3. 我很遗憾 B、C、D 发生在这个分支上;我希望我在 A 之后分支并且它们发生在另一个分支上。
Make a new branch otherbranch
, and then git reset --hard A
. The current branch now ends at A, with otherbranch
stemming from it.
创建一个新分支otherbranch
,然后git reset --hard A
. 当前分支现在以 A 结束,并otherbranch
源于它。
(Of course you could also use a hard reset because you wish B, C, and D had never happened at all.)
(当然,您也可以使用硬重置,因为您希望 B、C 和 D 根本没有发生过。)
回答by qinmu2127
You don't have to force yourself to remember differences between them. Think of how you actually made a commit.
您不必强迫自己记住它们之间的差异。想想你实际上是如何进行提交的。
1.Make some changes.
1.做一些改变。
2.git add .
2.git 添加。
3.gc -m "I did Something"
3.gc -m "我做了某事"
Soft, Mixed and Hard is the way enabling you to give up the operations you did from 3 to 1.
Soft、Mixed 和 Hard 是使您能够放弃从 3 到 1 所做的操作的方式。
Soft "pretended" to never see you have did "gc -m".
软“假装”从来没有看到你做过“gc -m”。
Mixed "pretended" to never see you have did "git add ."
混合“假装”从来没有看到你做过“git add”。
Hard "pretended" to never see you have made file changes.
很难“假装”永远不会看到您对文件进行了更改。
回答by Suresh Sharma
Before going into these three option one must understand 3 things.
在进入这三个选项之前,必须了解三件事。
1) History/HEAD
1) 历史/头部
2) Stage/index
2) 阶段/索引
3) Working directory
3) 工作目录
reset --soft : History changed, HEAD changed, Working directory is not changed.
reset --soft :历史改变,HEAD改变,工作目录没有改变。
reset --mixed : History changed, HEAD changed, Working directory changed with unstaged data.
reset --mixed :历史已更改,HEAD 已更改,工作目录已更改为未暂存数据。
reset --hard : History changed, HEAD changed, Working directory is changed with lost data.
reset --hard :历史改变,HEAD改变,工作目录因丢失数据而改变。
It is always safe to go with Git --soft. One should use other option in complex requirement.
使用 Git --soft 总是安全的。在复杂的需求中应该使用其他选项。
回答by De Novo
There are a number of answers here with a misconception about git reset --soft
. While there is a specific condition in which git reset --soft
will only change HEAD
(starting from a detached head state), typically (and for the intended use), it moves the branch reference you currently have checked out.Of course it can't do this if you don't have a branch checked out (hence the specific condition where git reset --soft
will only change HEAD
).
这里有许多答案对git reset --soft
. 虽然有一个特定的条件git reset --soft
只会改变HEAD
(从分离的头部状态开始),通常(和预期用途),它会移动您当前已检出的分支引用。当然,如果您没有检出分支,则无法执行此操作(因此特定条件 wheregit reset --soft
只会更改HEAD
)。
I've found this to be the best way to think about git reset
. You're not just moving HEAD
(everything does that), you're also moving the branch ref, e.g., master
. This is similar to what happens when you run git commit
(the current branch moves along with HEAD
), except instead of creating (and moving to) a newcommit, you move to a priorcommit.
我发现这是思考git reset
. 你不只是在移动HEAD
(一切都这样做),你也在移动分支 ref,例如,master
。这与运行时发生的情况类似git commit
(当前分支与 一起移动HEAD
),除了不是创建(并移动到)新提交,而是移动到先前的提交。
This is the point of reset
, changing a branchto something other than a new commit, not changing HEAD
.You can see this in the documentation example:
这就是将分支reset
更改为新提交以外的内容,而不是更改. HEAD
您可以在文档示例中看到这一点:
Undo a commit, making it a topic branch
$ 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.
撤消提交,使其成为主题分支
$ git branch topic/wip (1) $ git reset --hard HEAD~3 (2) $ git checkout topic/wip (3)
- 您已经进行了一些提交,但意识到它们进入“master”分支还为时过早。您想继续在主题分支中完善它们,因此从当前 HEAD 创建“主题/擦除”分支。
- 回滚主分支以摆脱这三个提交。
- 切换到“topic/wip”分支并继续工作。
What's the point of this series of commands? You want to move a branch, here master
, so while you have master
checked out, you run git reset
.
这一系列命令的意义何在?您想在此处移动一个分支,master
因此在您master
签出时,您运行git reset
.
The top voted answer here is generally good, but I thought I'd add this to correct the several answers with misconceptions.
这里投票最高的答案通常很好,但我想我会添加这个来纠正几个有误解的答案。
Change your branch
改变你的分支
git reset --soft <ref>
: resets the branch pointer for the currently checked out branch to the commit at the specified reference, <ref>
. Files in your working directory and index are not changed. Committing from this stage will take you right back to where you were before the git reset
command.
git reset --soft <ref>
:将当前检出分支的分支指针重置为指定引用处的提交,<ref>
。工作目录和索引中的文件不会更改。从这个阶段提交将带你回到你在git reset
命令之前的位置。
Change your index too
也改变你的索引
git reset --mixed <ref>
git reset --mixed <ref>
or equivalently
或等效地
git reset <ref>
:
git reset <ref>
:
Does what --soft
does ANDalso resets the index to the match the commit at the specified reference. While git reset --soft HEAD
does nothing (because it says move the checked out branch to the checked out branch), git reset --mixed HEAD
, or equivalently git reset HEAD
, is a common and useful command because it resets the index to the state of your last commit.
做什么--soft
呢AND也是该指数将匹配提交在规定的基准复位。虽然git reset --soft HEAD
什么都不做(因为它说将检出分支移动到检出分支)git reset --mixed HEAD
,或等效地git reset HEAD
,是一个常见且有用的命令,因为它将索引重置为您上次提交的状态。
Change your working directory too
也更改您的工作目录
git reset --hard <ref>
: does what --mixed
does ANDalso overwrites your working directory. This command is similar to git checkout <ref>
, except that (and this is the crucial point about reset
) all forms of git reset
move the branch ref HEAD
is pointing to.
git reset --hard <ref>
:做什么--mixed
呢AND也覆盖你的工作目录。该命令类似于git checkout <ref>
,除了(这是关于 的关键点reset
)分支 ref指向的所有形式的git reset
移动HEAD
。
A note about "such and such command moves the HEAD":
关于“某某命令移动 HEAD”的注释:
It is not useful to say a command moves the HEAD
. Any command that changes where you are in your commit history moves the HEAD
. That's what the HEAD
is, a pointer to wherever you are. HEAD
is you, and so will move whenever you do.
说命令移动HEAD
. 任何更改您在提交历史记录中的位置的命令都会移动HEAD
. 这就是HEAD
is,指向您所在位置的指针。HEAD
是你,所以你会移动。