你能解释一下“git reset”在纯英文中的含义吗?
我看到有趣的帖子解释了有关git reset
细微之处。
不幸的是,我对它的了解越多,看起来就越不完全理解它。 我来自SVN背景,Git是一个全新的范例。 我很轻松,但Git技术性更强。
我认为git reset
接近于hg revert
,但似乎有差异。
那么git reset
做什么? 请详细说明以下内容:
--hard
, - --soft
和--merge
; HEAD
使用的奇怪符号,如HEAD^
和HEAD~1
; HEAD
和您的全球压力水平造成的后果。 一般来说, git reset
的功能是取当前分支并将其重置为指向其他地方,并且可能带来索引和工作树。 更具体地说,如果您的主分支(当前签出)如下所示:
- A - B - C (HEAD, 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)
记住,重置不会进行提交,它只是更新一个分支(这是一个提交的指针)指向一个不同的提交。 其余的只是你的索引和工作树发生的细节。
用例
我在下一节的各种选项描述中涵盖了许多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状态的本地修改(或未跟踪文件)。 当你意识到你做了一些不好的提交时,请使用它,但是你想保留所有你已经完成的工作,这样你就可以修复它并重新提交。 为了提交,你必须再次将文件添加到索引( git add ...
)。
--soft
不会触摸索引或工作树。 所有文件与--mixed
一样--mixed
,但所有更改都显示为使用git状态changes 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
视为“n在HEAD之前提交”或“HEAD的第n代祖先”。 HEAD^
(或HEAD^1
)也表示提交的第一个父代。 HEAD^2
表示提交的第二个父代。 请记住,正常的合并提交有两个父母 - 第一个父母是合并提交,第二个父母是合并的提交。 一般来说,合并实际上可以有许多父母(章鱼合并)。 ^
和~
运算符可以串成,如在HEAD~3^2
,第三代祖先的第二个亲本HEAD
, HEAD^^2
,的第一个亲本的第二个亲本HEAD
,甚至HEAD^^^
,相当于HEAD~3
。 请记住,在git
你有:
HEAD
指针,它告诉你什么承诺你的工作 请详细说明以下内容:
--hard
--soft
, - --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
擦除所有东西,并在新的提交中开始一个新的石板。
在Pro Git博客中发布的重置解密功能对git reset
和git checkout
提供了一个非常简单的解释。
在该帖子顶部的所有有用讨论之后,作者将规则简化为以下简单的三个步骤:
基本上就是这样。 reset
命令以特定的顺序覆盖这三棵树,当你告诉它时停止。
--soft
停止) --hard
,否则停下来) 还有--merge
和--keep
选项,但我现在宁愿让事情更简单 - 这将是另一篇文章。
上一篇: Can you explain what "git reset" does in plain english?