【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
我看到有趣的帖子解释了关于git reset
微妙之处。
不幸的是,我读的越多,我就越不能完全理解它。 我来自SVN背景,Git是一个全新的范例。 我很容易变得善变,但Git更具技术性。
我认为git reset
接近hg revert
,但似乎存在差异。
那么git reset
究竟做了什么? 请包括以下详细说明:
- 选项
--hard
, ---soft
和--merge
; - 与
HEAD
使用的奇怪符号,如HEAD^
和HEAD~1
; - 具体用例和工作流程;
- 对工作副本,
HEAD
和您的全球压力水平的影响。
#1楼
当您提交git的东西时,首先必须暂存(添加到索引)您的更改。 这意味着在git认为它们是提交的一部分之前,你必须git添加你想要包含在这个提交中的所有文件。 让我们先来看看git repo的图像:

所以,现在很简单。 我们必须在工作目录中工作,创建文件,目录和所有。 这些更改是未跟踪的更改。 要跟踪它们,我们需要使用git add命令将它们添加到git索引。 一旦将它们添加到git索引中。 如果我们想将它推送到git存储库,我们现在可以提交这些更改。
但突然间我们知道我们提交了一个额外的文件,我们在索引中添加了不需要推入git存储库。 这意味着我们不希望索引中的该文件。 现在的问题是如何从git索引中删除该文件,因为我们使用git add将它们放在索引中,所以使用git rm是合乎逻辑的? 错误! git rm将简单地删除该文件并将删除添加到索引中。 那么现在该怎么办:
使用:-
git重置
它清除您的索引,保持您的工作目录不变。 (只是取消暂停一切)。
它可以与许多选项一起使用。 使用git reset有三个主要选项: - hard, - soft和--mixed 。 重置时,这些会影响除HEAD指针之外的重置。
首先, - 硬重置一切。 您当前的目录将完全像您一直关注该分支一样。 工作目录和索引将更改为该提交。 这是我经常使用的版本。 git reset --hard就像svn revert 。
接下来,完全相反的-soft ,不会重置工作树和索引。 它只移动HEAD指针。 这使您的当前状态的任何更改都与您在目录中切换到的提交不同,并且“暂存”以进行提交。 如果您在本地进行提交但尚未将提交推送到git服务器,则可以重置为先前的提交,并重新发送一个良好的提交消息。
最后, - mix复制索引,但不重置工作树。 因此,所有更改仍然存在,但是“未分级”并且需要git add'ed或git commit -a 。 我们有时会使用这个,如果我们使用git commit -a承诺了更多,我们可以使用git reset -mixed返回提交,添加我们想要提交的东西并提交它们。
git revert和git reset之间的区别 : -
在简单的话,git的复位是“修复未提交的错误”和Git将其还原为命令,以“修复COMMITED错误”的命令。
这意味着如果我们在某些更改中犯了一些错误并提交并将其推送到git repo,那么git revert就是解决方案。 如果我们在推送/提交之前已经识别出相同的错误,我们可以使用git reset来解决问题。
我希望它可以帮助你摆脱困惑。
#2楼
一般来说, git reset
的功能是获取当前分支并将其重置为指向其他位置,并可能带来索引和工作树。 更具体地说,如果您的主分支(当前已检出)是这样的:
- A - B - C (HEAD, master)
并且你意识到你希望master指向B而不是C,你将使用git reset B
将其移动到那里:
- A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore
题外话:这与结账不同。 如果你运行git checkout B
,你会得到这个:
- A - B (HEAD) - C (master)
你最终处于一个独立的HEAD状态。 HEAD
,工作树,索引全部匹配B
,但主分支在C
处留下。 如果你在这一点上做了一个新的提交D
,你会得到这个,这可能不是你想要的:
- A - B - C (master)
\
D (HEAD)
请记住,reset不会进行提交,它只是更新一个分支(指向提交的指针)以指向不同的提交。 其余的只是索引和工作树会发生什么的详细信息。
用例
我git reset
在下一节中对各种选项的描述中介绍git reset
许多主要用例。 它可以真正用于各种各样的事情; 常见的线程是所有这些都涉及重置分支,索引和/或工作树以指向/匹配给定的提交。
要小心的事情
--hard
可能会让你真的失去工作。 它会修改您的工作树。git reset [options] commit
会导致你(丢弃)提交。 在上面的玩具示例中,我们丢失了提交C
它仍然在回购中,您可以通过查看git reflog show HEAD
或git reflog show master
找到它,但它实际上不能从任何分支访问。Git会在30天后永久删除此类提交,但在此之前,您可以通过再次指向分支来恢复C(
git checkout C; git branch <new branch name>
)。
参数
解释手册页,最常见的用法是git reset [<commit>] [paths...]
,它会将给定路径重置为给定提交的状态。 如果未提供路径,则重置整个树,如果未提供提交,则将其视为HEAD(当前提交)。 这是git命令的常见模式(例如checkout,diff,log,虽然确切的语义各不相同),所以它不应该太令人惊讶。
例如, git reset other-branch path/to/foo
所有内容重置为其他分支中的状态, git reset -- .
将当前目录重置为HEAD中的状态,并且简单的git reset
会将所有内容重置为HEAD中的状态。
主要工作树和索引选项
有四个主要选项可以控制在重置期间工作树和索引发生的情况。
请记住,索引是git的“临时区域” - 当你说准备提交git add
时,事情就会发生。
--hard
使一切都与你重置的提交相匹配。 这可能是最容易理解的。 您所有的本地更改都会被破坏。 一个主要用途是吹走你的工作而不是切换提交:git reset --hard
意味着git reset --hard HEAD
,即不要更改分支但是去除所有本地更改。 另一种是简单地将分支从一个地方移动到另一个地方,并使索引/工作树保持同步。 这可以真正让你失去工作,因为它会修改你的工作树。 非常确定你想在运行任何reset --hard
之前扔掉当地的工作 -reset --hard
。--mixed
是默认值,即git reset
意味着git reset --mixed
。 它重置索引,但不重置工作树。 这意味着您的所有文件都是完整的,但原始提交与您重置的文件之间的任何差异都将显示为具有git status的本地修改(或未跟踪文件)。 当你意识到你做了一些不好的提交时,使用它,但你想保留你已经完成的所有工作,这样你就可以修复它并重新发送。 为了提交,你必须再次将文件添加到索引(git add ...
)。--soft
不会触及索引或工作树。 所有文件都与--mixed
一样完整,但所有更改都显示为changes to be committed
使用git statuschanges to be committed
(即在准备提交时签入)。 当你意识到你做了一些不好的提交时使用它,但是工作都很好 - 你需要做的就是以不同的方式重新发送它。 索引是不变的,因此您可以根据需要立即提交 - 结果提交将具有与重置之前相同的内容。--merge
最近被添加,旨在帮助您中止失败的合并。 这是必要的,因为git merge
实际上允许您尝试与脏工作树(具有本地修改的工作树)合并,只要这些修改在不受合并影响的文件中。git reset --merge
重置索引(如--mixed
- 所有更改都显示为本地修改),并重置受合并影响的文件,但--mixed
其他文件。 这将有望恢复在糟糕合并之前的一切。 你通常会将它用作git reset --merge
(意思是git reset --merge HEAD
),因为你只想重置合并,而不是实际移动分支。 (HEAD
尚未更新,因为合并失败)更具体地说,假设您已经修改了文件A和B,并且尝试在修改了文件C和D的分支中进行合并。由于某种原因合并失败,并且您决定中止它。 你使用
git reset --merge
。 它将C和D带回到它们在HEAD
,但仅对A和B进行修改,因为它们不是尝试合并的一部分。
想知道更多?
我确实认为man git reset
对此非常有用 - 也许你需要对git的工作方式有一点了解才能真正沉入其中。 特别是,如果您花时间仔细阅读它们,那些详细说明索引和工作树中所有各种选项和案例的文件状态的表非常有用。 (但是,它们非常密集 - 它们以非常简洁的形式传达了大量上述信息。)
奇怪的表示法
你提到的“奇怪的符号”( HEAD^
和HEAD~1
)只是指定提交的简写,而不必使用像3ebe3f6
这样的哈希名称。 它完全记录在git-rev-parse手册页的“指定修订版”部分 ,包含大量示例和相关语法。 插入符号和波形符号实际上意味着不同的东西 :
-
HEAD~
是HEAD~1
缩写,表示提交的第一个父级。HEAD~2
表示提交的第一个父亲的第一个父亲。 将HEAD~n
想象为“在HEAD之前提交n”或“HEAD的第n代祖先”。 -
HEAD^
(或HEAD^1
)也表示提交的第一个父级。HEAD^2
表示提交的第二个父级。 请记住,正常的合并提交有两个父级 - 第一个父级是合并的提交,第二个父级是合并的提交。 一般来说,合并实际上可以有任意多的父母(章鱼合并)。 - 所述
^
和~
运算符可以串成,如在HEAD~3^2
,第三代祖先的第二个亲本HEAD
,HEAD^^2
,的第一个亲本的第二个亲本HEAD
,甚至HEAD^^^
,相当于HEAD~3
。

#3楼
请记住,在git
你有:
-
HEAD
指针 ,它告诉您正在进行的提交 - 工作树 ,表示系统上文件的状态
- 暂存区域 (也称为索引 ),它“ 分级 ”更改,以便以后可以一起提交
请包括以下详细说明:
--hard
, ---soft
和--merge
;
随着危险程度的增加:
-
--soft
移动HEAD
但不触及暂存区域或工作树。 -
--mixed
移动HEAD
并更新暂存区域,但不更新工作树。 -
--merge
移动HEAD
,重置暂存区域,并尝试将工作树中的所有更改移动到新的工作树中。 -
--hard
移动HEAD
并将你的临时区域和工作树调整到新HEAD
,扔掉所有东西。
具体用例和工作流程;
- 如果你想转移到另一个提交并修补一些东西而不“失去你的位置”,请使用
--soft
。 你需要这个很少见。
-
# 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
擦除所有内容并在新提交中开始新的事件。
#4楼
请注意,这是一个简化的解释,旨在作为了解这一复杂功能的第一步。
对于想要在每个命令之后可视化项目状态的视觉学习者可能会有所帮助:
对于那些使用打开颜色的终端的人(git config --global color.ui auto):
git reset --soft A
你会看到B和C的东西是绿色的(上演并准备提交)
git reset --mixed A
(或git reset A
),你会看到B和C的东西是红色的(未分阶段,准备上演(绿色),然后提交)
git reset --hard A
你将不会再看到B和C的变化(就好像它们从未存在过)
或者对于那些使用像'Tower'或'SourceTree'这样的GUI程序的人
git reset --soft A
,你会在'staged files'区域看到B和C的东西准备提交
git reset --mixed A
(或git reset A
),你会在'unstaged files'区域看到B和C的东西,准备移动到staged然后提交
git reset --hard A
你将不会再看到B和C的变化(就好像它们从未存在过)
#5楼
TL; DR
git reset
Staging重置为上次提交。 使用--hard
还可以将工作目录中的文件重置为上次提交。
更长的版本
但这显然是简单化的,因此许多相当冗长的答案。 在撤消更改的上下文中,我更有意义地阅读git reset
。 例如看到这个:
如果git revert是一种撤消更改的“安全”方式,您可以将git reset视为危险方法。 使用git reset撤消(并且任何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
来源:oschina
链接:https://my.oschina.net/u/3797416/blog/3149192