简体   繁体   English

“git reset HEAD”和“git reset HEAD”有什么区别。

[英]What is the difference between “git reset HEAD” and “git reset HEAD .”

Is this a shorthand like for example how git add -A is for doing both git add.这是一个简写,例如git add -A是如何同时进行git add. & git add -u & git add -u

See this question for context https://stackoverflow.com/a/22207257/7680918#请参阅此问题以了解上下文https://stackoverflow.com/a/22207257/7680918#

As it turns out, Git is smart enough not to drop a stash if it doesn't apply cleanly.事实证明,Git 足够聪明,不会在不干净应用的情况下丢弃存储。 I was able to get to the desired state with the following steps:我能够通过以下步骤获得所需的 state:

  1. To unstage the merge conflicts: git reset HEAD.要取消合并冲突: git reset HEAD. (note the trailing dot) (注意尾随点)
  2. To save the conflicted merge (just in case): git stash保存冲突的合并(以防万一): git stash
  3. To return to master: git checkout master返回master: git checkout master
  4. To pull latest changes: git fetch upstream; git merge upstream/master拉取最新更改: git fetch upstream; git merge upstream/master git fetch upstream; git merge upstream/master
  5. To correct my new branch: git checkout new-branch; git rebase master更正我的新分支: git checkout new-branch; git rebase master git checkout new-branch; git rebase master
  6. To apply the correct stashed changes (now 2nd on the stack): git stash apply stash@{1}要应用正确的隐藏更改(现在是堆栈中的第二个): git stash apply stash@{1}

TL;DR TL;博士

The linked answer perhaps should not have suggested git reset HEAD.链接的答案可能不应该建议git reset HEAD. . . It works, but only if you're at the top of the working tree.它有效,但前提是您位于工作树的顶部。 A simple git reset (with no options and no additional arguments) is probably a better idea.一个简单的git reset (没有选项也没有额外的参数)可能是一个更好的主意。

Long

Here's some background to know before reading the git reset documentation :在阅读git reset文档之前,这里有一些背景知识:

  • A pathspec is a file name, possibly including path components such as dir/file or a/b/file.ext , or just file.ext or whatever. pathspec是一个文件名,可能包括路径组件,例如dir/filea/b/file.ext ,或者只是file.ext或其他。

  • The git reset command can affect up to three things: the current branch as seen through the name HEAD , Git's index , and files in your working tree . git reset命令最多可以影响三件事:通过名称HEAD看到的当前分支、Git 的索引工作树中的文件。

  • The git reset command is overly complicated: it has multiple "modes of operation", as it were. git reset命令过于复杂:它有多种“操作模式”,实际上。

To talk about how git reset affects HEAD , we would need to discuss how branch names work 1 and how HEAD is attached to a branch name.要讨论git reset如何影响HEAD ,我们需要讨论分支名称如何工作1以及HEAD如何附加到分支名称。 2 But the kind of git reset we'll talk about here specifically does not affect HEAD itself, so except for the footnotes, we won't bother. 2但是我们这里具体讲的git reset不会影响HEAD本身,所以除了脚注,我们就不多说了。 It does affect Git's index, though, so let's talk about Git's index before we proceed.不过,它确实会影响 Git 的索引,所以在继续之前让我们先谈谈 Git 的索引。


1 In a nutshell, a branch name points to a commit (by storing a raw commit hash ID). 1简而言之,分支名称指向一个提交(通过存储原始提交 hash ID)。 The name HEAD is attached to the branch name, so by "moving your HEAD ", git reset changes which commit it is to which the branch name points.名称HEAD附加到分支名称,因此通过“移动您的HEAD ”, git reset分支名称指向的提交更改。 That is, Git writes a different commit hash ID into the branch name.也就是说,Git 将不同的提交 hash ID 写入分支名称。

2 The git checkout command, and the new-in-Git-2.23 git switch command, do this "attaching" while checking out a commit using some branch name. 2 git checkout命令和 new-in-Git-2.23 git switch命令,在使用某个分支名称签出提交时执行此“附加”。


Git's index Git的索引

Git's index is a persisent (stored-on-disk) data structure that, for the most part, records what Git needs to know in order for Git to make the next commit. Git 的索引是一种持久(存储在磁盘上)数据结构,在大多数情况下,它记录了 Git 需要知道的内容,以便 Git 进行下一次提交。 The way I like to put this is that the index holds your proposed next commit , or at least, its snapshot.我喜欢这样说的方式是索引保存您提议的下一次提交,或者至少是它的快照。 In this way, the index fulfills its role as your staging area , which is why it also has this name.这样,索引就完成了它作为暂存区的作用,这就是它也有这个名字的原因。 But the index does more than just store the proposed next commit.但索引不仅仅存储提议的下一次提交。 In particular, when you are doing a merge and have merge conflicts , the index takes on an expanded role.特别是,当您进行合并并发生合并冲突时,索引将扮演扩展角色。

First, though, let's say a bit more about this staging-area role.不过,首先,让我们多谈谈这个暂存区角色。 As the staging area, what the index holds is a full copy of every source file .作为暂存区,索引保存的是每个源文件的完整副本 It does not hold only changed files.它不仅保存更改的文件。 The git status command specifically mentions the changed files, and specifically does not mention the unchanged files. git status命令专门提到了改变的文件,而具体没有提到没有改变的文件。 But the staging area holds all the files.但是暂存区包含所有文件。

These files originally came out of the current commit.这些文件最初来自当前提交。 If you have not replaced a file in the staging area, and it's still the one that came out of the current commit, then it matches the current commit.如果您没有替换暂存区域的文件,并且它仍然是当前提交的文件,那么它当前提交匹配。 So git status just doesn't mention it.所以git status只是没有提到它。 It's still there!它还在那里! It's just not mentioned!只是没有提到! But if you did change a working tree file, and then run git add , you told Git: Eject the file that you have now, and put in this other file, using the same name.但是,如果您确实更改了工作树文件,然后运行git add ,您告诉 Git:弹出您现在拥有的文件,并使用相同的名称放入另一个文件。 So now the staged file is different from the committed file.所以现在暂存文件与提交文件不同

It doesn't matter much for our particular purpose here, but it's worth noting that the staged copy of each file is already in Git's compressed and de-duplicated format .对于我们在这里的特定目的而言,这并不重要,但值得注意的是,每个文件的暂存副本已经采用 Git 的压缩和去重格式 This is how files look when they're in commits: the name is stored somewhere else—as it is in the index—and the contents are stored compressed and de-duplicated, as they are in Git's index.这就是文件在提交时的样子:名称存储在其他地方——就像它在索引中一样——并且内容被压缩和去重复存储,就像它们在 Git 的索引中一样。 The files in your working tree are not compressed and not de-duplicated, 3 so git add has to compress and de-duplicate them before storing them into Git's index, so as to be staged for the new commit.你的工作树中的文件没有被压缩和去重, 3所以git add必须在将它们存储到 Git 的索引之前对其进行压缩和去重,以便为新的提交暂存。

The point of all of this is to make you aware of these things:所有这些的目的是让你意识到这些事情:

  • What's in Git's index is in commit-able format. Git 索引中的内容是可提交的格式。
  • Every file that is going to be in the next commit is always staged.在下一次提交中的每个文件总是被暂存。 Removing a file from the staging area means that the entire file won't be in the next commit .从暂存区移除文件意味着整个文件不会在下一次提交中。
  • git status doesn't bother to tell you about files that are the same in the current commit as they are in the index. git status不会告诉您当前提交中与索引中相同的文件。 It only says staged for commit when these files are different in some way.当这些文件以某种方式同时,它只说暂存提交 That way, even if your commits all hold 10,000 files each, you only need to pay attention to the two or three files you changed .这样,即使您的提交都包含 10,000 个文件,您只需要注意您更改的两三个文件

When you go to make a new commit, eg, by running git commit , what Git does is make the new commit using the index copies of the files as the snapshot.当您 go 进行提交时,例如,通过运行git commit , Git 所做的就是使用文件的索引副本作为快照进行新提交。 Since they're already in the format used for commits, this goes very fast.由于它们已经采用了用于提交的格式,因此速度非常快。

In this particular case, though, we're concerned with the index after a merge conflict.但是,在这种特殊情况下,我们关心的是合并冲突后的索引。 So we need to understand the expanded index, not just the normal everyday proposed-next-snapshot index.所以我们需要了解扩展索引,而不仅仅是普通的日常建议下一个快照索引。


3 Technically, whether working tree files are de-duplicated is up to your operating system. 3从技术上讲,是否对工作树文件进行重复数据删除取决于您的操作系统。 Using ZFS on Linux or FreeBSD, for instance, you can configure the file system itself to do de-duplication.例如,在 Linux 或 FreeBSD 上使用 ZFS,您可以配置文件系统本身进行重复数据删除。 That's irrelevant to Git, which does its own separate de-duplication.这与 Git 无关,它自己进行单独的重复数据删除。


The expanded index扩展索引

In the normal index setup, every file is at what Git calls stage zero .在正常的索引设置中,每个文件都处于 Git 称为stage zero的位置。 We can see this—and the staging numbers—using git ls-files --stage .我们可以使用git ls-files --stage看到这一点以及暂存编号。 Here is a snippet of what is in a Git index for the Git repository for Git:以下是 Git 的 Git 存储库的 Git 索引中的内容片段:

100644 908330a0a3d5d1c1bad56544ba5bb18c3b783c84 0       .travis.yml
100644 5ba86d68459e61f87dae1332c7f2402860b4280c 0       .tsan-suppressions
100644 65651beada79b6267b1d0bda518a88269374cfdf 0       CODE_OF_CONDUCT.md
100644 536e55524db72bd2acf175208aef4f3dfc148d42 0       COPYING
100644 ddb030137d54ef3fb0ee01d973ec5cee4bb2b2b3 0       Documentation/.gitattributes
100644 9022d4835545cbf40c9537efa8ca9a7678e42673 0       Documentation/.gitignore
100644 45465bc0c98f5d88cfe1ade092d29b5dc32c1e23 0       Documentation/CodingGuidelines

(the full index contents run for almost 4000 lines: one entry per file, and there are almost 4000 files). (完整的索引内容运行了将近 4000 行:每个文件一个条目,并且几乎有 4000 个文件)。 The staging number is the third field in each line, and as you can see, each one is zero here.分段编号是每一行中的第三个字段,如您所见,这里每个字段都为零。 This means there are no merge conflicts in progress.这意味着没有正在进行的合并冲突。 The last field holds the file's name, as seen in the index;最后一个字段包含文件的名称,如索引中所示; note that many names have embedded slashes (this is always a forward slash, even on Windows).请注意,许多名称都嵌入了斜杠(这始终是正斜杠,即使在 Windows 上也是如此)。

When you have a merge conflict, what Git does is leave, in the index, three —or more precisely, up to three—versions of each file .当您发生合并冲突时,Git 所做的是在索引中保留每个文件三个(或更准确地说,最多三个)版本。 4 These three files are at three nonzero staging index numbers. 4这三个文件位于三个非零暂存索引号处。 Staging number 1 means that a file in the index is from the merge base commit.暂存编号 1 表示索引中的文件来自合并基本提交。 Staging number 2 means that this file is from the "ours" or HEAD commit, and staging number 3 means that the file is from the "theirs" commit.暂存编号 2 表示该文件来自“我们的”或HEAD提交,而暂存编号 3 表示该文件来自“他们的”提交。 The existence of any entries at a nonzero stage indicates that this particular file has a merge conflict.在非零阶段存在任何条目表明该特定文件存在合并冲突。

One way you can think of this is that each file has up to four "slots".您可以想到的一种方法是每个文件最多有四个“插槽”。 Slot zero is used if the file is not conflicted .如果文件不冲突,则使用零位。 Otherwise, slots 1, 2, and/or 3 are occupied.否则,插槽 1、2 和/或 3 将被占用。 So, if a file is in merge-conflict state, it has a nonzero slot number (and there might be more entries for this same file, with other slot numbers).因此,如果一个文件处于合并冲突 state 中,则它具有非零插槽编号(并且同一文件可能有更多条目,以及其他插槽编号)。 Otherwise it has a zero slot number (and there are no more entries for this file).否则,它的插槽号为零(并且此文件没有更多条目)。

Whenever any file is in merge-conflict state, Git will refuse to make a new commit .每当任何文件发生合并冲突时 state, Git 将拒绝进行新的提交 It literally can't, because only slot-zero entries can go into commits: there's no space for a slot number in the commit.它实际上不能,因为只有零槽条目可以 go 进入提交:提交中没有用于槽号的空间。 So, before you can commit, you must resolve the conflicts .所以,在你可以提交之前,你必须解决冲突

Exactly how you resolve the conflicts is up to you.究竟如何解决冲突取决于您自己。 What Git requires from you is simple though: it just needs you to tell Git: Take out the slot 1, 2, and/or 3 entries entirely. Git对您的要求很简单:它只需要您告诉 Git:完全取出插槽 1、2 和/或 3 条目。 You can do that in many ways:您可以通过多种方式做到这一点:

  • git rm will remove these entries. git rm将删除这些条目。
  • git add will copy a file from your working tree into slot zero in the index, removing the nonzero entries. git add会将工作树中的文件复制到索引中的零槽中,删除非零条目。
  • git reset and git restore can both put in a stage-zero file and hence remove the nonzero entries as well. git resetgit restore都可以放入零阶段文件,因此也可以删除非零条目。

This last one is going to be the key to the answer.最后一个将是答案的关键。


4 The original index design was supposed to allow more than three here, but in fact nothing seems to make use of this. 4最初的索引设计应该在这里允许超过三个,但实际上似乎没有任何利用这一点。


Let's look back at the question again让我们再回头看看这个问题

The original question kicking all this off was what, if any, difference there is between:开始这一切的最初问题是:

git reset HEAD

and:和:

git reset HEAD .

and then how this was used in another StackOverflow answer (which consisted of running six listed commands).然后是如何在另一个 StackOverflow 答案中使用它(包括运行六个列出的命令)。

The git reset HEAD. git reset HEAD. command is perhaps better written as:命令可能最好写成:

git reset HEAD -- .

to make it clear that .说清楚. here is a pathspec .这是一个pathspec We now turn to the git reset documentation , specifically the SYNOPSIS section, which reads:我们现在转向git reset文档,特别是 SYNOPSIS 部分,内容如下:

SYNOPSIS概要

git reset [-q] [<tree-ish>] [--] <pathspec>… git reset [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>] git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>…] git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]

There are some syntactic tricks to understand here: things in square brackets [] are optional, things in angle brackets <> are to be replaced with some non-empty string, and ellipses ( ) represent "one or more of whatever we just said".这里有一些语法技巧需要理解:方括号[]中的内容是可选的,尖括号<>中的内容将替换为一些非空字符串,省略号 ( ) 表示“我们刚才所说的一个或多个”。 (In this case, that's one or more pathspecs.) Parentheses surround alternatives that are separated with a vertical bar | (在这种情况下,这是一个或多个路径规范。)括号包围用竖线|分隔的备选方案。 , so (--patch | -p) means that you may write either --patch or -p here. , 所以(--patch | -p)意味着你可以在这里写--patch-p These syntactic gimmicks are mostly standard across most Unix/Linux documentation, in SYNOPSIS sections.这些句法噱头在大多数 Unix/Linux 文档中大多是标准的,在 SYNOPSIS 部分。

There are more tricks here, specific to Git: the word tree-ish means anything acceptable according to the gitrevisions documentation, as long as Git can turn that into an internal tree object specifier .这里还有更多技巧,特定于 Git:根据 gitrevisions 文档, tree-ish一词意味着任何可以接受的东西,只要 Git 可以将其转换为内部树 ZA8CFDE6331BD59EB2AC96F8911C4B66 说明符 In this case, that means anything that specifies a commit works.在这种情况下,这意味着任何指定提交的东西都有效。 HEAD specifies a commit—the current commit—so git reset HEAD matches this git reset <tree-ish> . HEAD指定了一个提交——当前提交——所以git reset HEAD匹配这个git reset <tree-ish>

The first synopsis entry requires git reset , allows an optional -q , allows an optional <tree-ish> , allows an optional -- , and then requires a <pathspec> .第一个概要条目需要git reset ,允许可选-q ,允许可选<tree-ish> ,允许可选-- ,然后需要<pathspec> So:所以:

git reset HEAD

does not match this form, because the pathspec is missing.与此形式不匹配,因为缺少路径规范。 But:但:

git reset HEAD .

does match this form: it omits the -- but that is allowed.确实匹配这种形式:它省略了--但这是允许的。

The second form in the synopsis section requires the git reset part, has an optional -q as before, allows an optional --pathspec-from-file —if that's used, --pathspec-file-nul can also be used—and then has an optional <tree-ish> .概要部分中的第二种形式需要git reset部分,像以前一样有一个可选的-q ,允许一个可选的--pathspec-from-file ——如果使用了,也可以使用--pathspec-file-nul ——然后有一个可选的<tree-ish> So:所以:

git reset HEAD

matches this form.匹配这个表格。 (This is a glitch in the documentation!) (这是文档中的一个小故障!)

The third form requires either --patch or -p so neither command matches this one.第三种形式需要--patch-p所以两个命令都不匹配这个。

The last form requires git reset (as always), then allows one of the options --soft , --mixed , --hard , --merge , or --keep , an optional -q , and an optional <commit> (note that this is not a <tree-ish> but specifically a commit ).最后一种形式需要git reset (一如既往),然后允许选项--soft--mixed--hard--merge--keep 、可选的-q和可选的<commit> (请注意,这不是<tree-ish>而是特别是commit )。 The:这:

git reset HEAD

command matches this form too.命令也匹配这种形式。 So git reset HEAD , without a dot as a pathspec, could be one of these.所以git reset HEAD ,没有点作为路径规范,可能是其中之一。

As I suggested above, this is a bit of a glitch in the documentation: which of the two allowable matches should git reset HEAD take?正如我上面所建议的,这是文档中的一个小故障: git reset HEAD应该采用两个允许匹配中的哪一个? We only learn this by reading on in the documentation (and even then we have to guess a bit, or try a test reset).我们只能通过阅读文档来了解这一点(即使这样,我们也必须猜测一下,或者尝试重置测试)。

The next section is the DESCRIPTION section.下一部分是描述部分。 It says that the kinds of git reset that use a pathspec它说使用路径规范的git git reset的种类

... reset the index entries for all paths that match the <pathspec> to their state at <tree-ish> . ...将与<pathspec>匹配的所有路径的索引条目重置为<tree-ish>的 state 。 (It does not affect the working tree or the current branch.) (它不会影响工作树或当前分支。)

What this means is that the state of the file(s) in the specified commit— HEAD , in this case—is copied into the index.这意味着将指定提交中的文件的 state(在本例中为HEAD )复制到索引中。 What's not quite mentioned (though it's at least partly covered in the next paragraph via a reference to git restore ) is that this has the same side effect of clearing out nonzero-stage entries as git add .没有完全提到的(尽管通过对git restore的引用在下一段中至少部分涵盖了)是,这具有与清除非零阶段条目相同的git add

So this answers what:所以这回答了什么:

git reset HEAD -- .

does: it resets, as in clears-out-conflicts as well as copying the HEAD commit copy of, each file matched by the pathspec .确实:它重置,如清除冲突以及复制与 pathspec 匹配的每个文件的HEAD提交副本. . .

That leaves us with the question: Which files are matched by the pathspec .这给我们留下了一个问题:哪些文件与 pathspec 匹配. ? ? There's a flaw in the current reset documentation.当前的重置文档存在缺陷。 It refers us to the gitglossary page , which tells us that pathspecs could be relative to the top of the working tree, or to the current working directory, and that each more-specific page (ie, the one for git reset ) should say.它向我们介绍了 gitglossary page ,它告诉我们 pathspecs 可以相对于工作树的顶部或当前工作目录,并且每个更具体的页面(即git reset的页面)都应该说。 It doesn't say.它没有说。 The fact is that .事实是. here is relative to the current working directory .这里是相对于当前工作目录的。 So if you're not at the top of the tree:因此,如果您不在树的顶部:

git reset HEAD -- .

means only the files in this directory and below .仅表示此目录及以下目录中的文件

Experimentation ( git rm --cached of some existing file, and git add of some new file) shows that git reset HEAD --.实验( git rm --cached一些现有文件,以及git add一些新文件)表明git reset HEAD --. restores to the index any file missing due to the git rm , and removes from the index any new file not in HEAD .将由于git rm丢失的任何文件恢复到索引,并从索引中删除任何不在HEAD中的新文件。 It might be nice if the documentation were clearer on this, but perhaps we can take the experimental results as definite / goal-behavior.如果文档对此更清楚可能会很好,但也许我们可以将实验结果视为确定/目标行为。

Let's move on to the other command:让我们继续执行另一个命令:

git reset HEAD

Does this mean git reset with no --pathspec-from-file options but a <tree-ish> , or does this mean git reset with no --hard or --mixed or whatever but a <commit> ?这是否意味着git reset没有--pathspec-from-file选项但<tree-ish> ,或者这是否意味着git reset没有--hard--mixed或除了<commit>之外的任何东西? Well, if it were the former, it would not supply any pathspecs at all.好吧,如果前者,它根本不会提供任何路径规范。 The idea behind --pathspec-from-file is to supply the pathspecs in a file, rather than on the command line, but that way there are some pathspecs. --pathspec-from-file背后的想法是在文件中而不是在命令行中提供路径规范,但这样就有一些路径规范。 If Git treats this as the former, there are no pathspecs at all.如果 Git 将其视为前者,则根本没有路径规范。

We can try a test here:我们可以在这里进行测试:

$ git reset HEAD^{tree}
error: object fcb94a429496c28fa7f95926e9d46840671d0d88 is a tree, not a commit
fatal: Could not parse object 'HEAD^{tree}'.

This uses the gitrevisions syntax to make sure that we supply git reset with a tree-ish, rather than a commit.这使用gitrevisions语法来确保我们提供git reset与树状,而不是提交。 The result is an immediate error.结果是立即出错。 Running git reset HEAD works, so it must be the case that this particular git reset is matching this with the fourth syntax, not the second.运行git reset HEAD有效,因此这个特定的git reset必须与第四个语法匹配,而不是第二个。 (The documentation should have omitted the square brackets around --pathspec-from-file .) (文档应该省略了--pathspec-from-file周围的方括号。)

The fourth syntax is the one described by the:第四种语法是由以下描述的:

git reset [<mode>] [<commit>]

section, which says:部分,其中说:

This form resets the current branch head to <commit> and possibly updates the index (resetting it to the tree of <commit> ) and the working tree depending on <mode> .此表单将当前分支头重置为<commit>并可能根据<mode>更新索引(将其重置为<commit>的树)和工作树。 If <mode> is omitted, defaults to --mixed .如果<mode>被省略,默认为--mixed [snip] [剪辑]

So this is a --mixed reset, since we omitted the <mode> parameter (which is one of those four choices enumerated in the synopsis).所以这是一个--mixed重置,因为我们省略了<mode>参数(这是概要中列举的四个选项之一)。 The commit we choose—which causes the current branch name to move to that commit—is the commit selected by HEAD .我们选择的提交(导致当前分支名称移动该提交)是HEAD选择的提交。 But HEAD is the commit selected by the current branch name.HEAD是当前分支名称选择的提交。 So the move is from some commit—let's call it "commit X"—to commit X. If you jump from where you are standing now but arrange to land where you are standing now, that wasn't really much of a move, was it?所以这个动作是来自某个提交——我们称之为“提交 X”——提交 X。如果你从你现在站立的地方跳下来但安排降落在你现在站立的地方,那并不是一个真正的移动,是它? :-) :-)

Anyway, this means that the resets the current branch head phrase becomes irrelevant: the current branch head just stays where it is.无论如何,这意味着重置当前分支头短语变得无关紧要:当前分支头只是停留在原处。 We move on to and possibly updates the index .我们继续并可能更新索引 Whether git reset updates the index depends on the <mode> , which we just said is --mixed , of which the documentation goes on to say this: git reset是否更新索引取决于<mode> ,我们刚才说的是--mixed ,其中文档继续说:

Resets the index but not the working tree...重置索引但不重置工作树...

So this copies the current commit back into the index.因此,这会将当前提交复制回索引中。 It's a bit like using a pathspec that matches every file, except that we don't need a pathspec at all, and in fact are forbidden from using one.这有点像使用匹配每个文件的路径规范,只是我们根本不需要路径规范,实际上禁止使用路径规范。 (Using a pathspec gets us into the first syntax, instead of this fourth syntax.) (使用路径规范让我们进入第一种语法,而不是第四种语法。)

As with git reset with a pathspec, this has the side effect of undoing any merge-conflict state: any nonzero stage entries in the index get replaced with their stage-zero copy from the commit.与使用git reset git 一样,这具有撤消任何合并冲突 state 的副作用:索引中的任何非零阶段条目都将替换为来自提交的阶段零副本。

Something that is not well documented, but has always been true of a standard --mixed reset, is that this kind of git reset will remove from Git's index any file that is not in the selected commit.没有很好的文档记录,但标准--mixed重置始终是正确的,这种git reset将从 Git 的索引中删除任何不在所选提交中的文件。 As I found by experimentation, the git reset HEAD --.我通过实验发现, git reset HEAD --. command behaves the same way here. command 在这里的行为方式相同。

Summary概括

Let me copy this again here:让我在这里再复制一次:

As it turns out, Git is smart enough not to drop a stash if it doesn't apply cleanly.事实证明,Git 足够聪明,不会在不干净应用的情况下丢弃存储。

This part means that the problem being addressed is:这部分意味着要解决的问题是:

<do some hacking>
<realize that this is the wrong commit>
$ git stash
$ git checkout somebranch
$ git stash pop
<receive merge conflict messages>

The git stash pop operation stopped in the middle of its first ( git stash apply ) step and has completely omitted, and will not run, its second ( git stash drop ) step here. git stash pop操作在其第一个( git stash apply )步骤的中间停止,完全省略,不会运行,它的第二个( git stash drop步骤放在这里)。

I was able to get to the desired state with the following steps:我能够通过以下步骤获得所需的 state:

  1. To unstage the merge conflicts: git reset HEAD.要取消合并冲突: git reset HEAD. (note the trailing dot) (注意尾随点)

This is where the question came in. A git reset --mixed HEAD , which can be spelled git reset , is probably a better approach here.这就是问题所在。 A git reset --mixed HEAD ,可以拼写为git reset ,在这里可能是更好的方法。 This puts the index back to the state before the git stash apply even started.这会在git stash apply开始之前将索引放回 state。

(Since we definitely don't need the result of this merge—we can re-create it any time later as long as we still have the two stash commits—we could just have run git reset --hard . But this particular guy did not do that.) (因为我们绝对不需要这个合并的结果——我们可以在以后任何时候重新创建它,只要我们仍然有两个存储提交——我们可以只运行git reset --hard 。但是这个特别的人做了不要那样做。)

  1. To save the conflicted merge (just in case): git stash保存冲突的合并(以防万一): git stash

This is quite unnecessary.这是完全没有必要的。 It makes two more commits—each stash entry is either two or three commits;它再进行两次提交——每个存储条目是两个或三个提交; see this old answer of mine —one of which is a duplicate of the current commit and one of which holds the tracked files from the working tree;请参阅我的这个旧答案——其中一个是当前提交的副本,其中一个包含工作树中的跟踪文件; then it runs git reset --hard (which we could have done earlier).然后它运行git reset --hard (我们本可以早点完成)。

  1. To return to master: git checkout master返回master: git checkout master

This of course does exactly what we'd expect.这当然完全符合我们的预期。 Because of the git reset --hard at the end of git stash , there are no staged or unstaged changes: the current commit, Git's index, and your working tree all match, and git status would say nothing to commit, working tree clean .由于git reset --hardgit stash结束时,没有暂存或未暂存的更改:当前提交、Git 的索引和您的工作树都匹配,并且git status nothing to commit, working tree clean BDworkingtree 2

  1. To pull latest changes: git fetch upstream; git merge upstream/master拉取最新更改: git fetch upstream; git merge upstream/master git fetch upstream; git merge upstream/master

This obtains new commits from a remote named upstream , then does whatever git merge upstream/master will do;这从名为upstream的远程获取新提交,然后执行git merge upstream/master将执行的任何操作; this obviously depends on the commits on upstream/master obtained in the git fetch vs the commits on the current ( master ) branch.这显然取决于在git fetch中获得的upstream/master上的提交与当前( master )分支上的提交。

If we make some assumptions—that master is normally in sync with upstream/master except when the upstream Git's users add new commits to upstream —this would do a simple fast-forward operation.如果我们做出一些假设——master 通常与upstream/master master ,除非上游 Git 的用户向upstream添加新提交——这将执行一个简单的快进操作。

  1. To correct my new branch: git checkout new-branch; git rebase master更正我的新分支: git checkout new-branch; git rebase master git checkout new-branch; git rebase master

This will do the usual rebase work.这将完成通常的变基工作。

  1. To apply the correct stashed changes (now 2nd on the stack): git stash apply stash@{1}要应用正确的隐藏更改(现在是堆栈中的第二个): git stash apply stash@{1}

If we had skipped the extra (unnecessary) stash earlier, git stash apply would do the desired thing here.如果我们之前跳过了额外的(不必要的)存储, git stash apply将在此处执行所需的操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 git reset HEAD和git reset HEAD〜有什么区别 - is there any difference between `git reset HEAD` and `git reset HEAD~` git reset --hard HEAD~1 和 git reset HEAD~1 --hard 之间的区别? - Difference between git reset --hard HEAD~1 and git reset HEAD~1 --hard? git checkout和有什么不一样? vs git reset --hard HEAD - What is the difference between git checkout . vs git reset --hard HEAD “git checkout -f”和“git reset --hard HEAD”有什么区别? - What is difference between “git checkout -f” and “git reset --hard HEAD”? “git checkout — .” 和有什么区别? 和“git reset HEAD --hard”? - What is the difference between “git checkout — .” and “git reset HEAD --hard”? 'git reset --hard HEAD~1' 和 'git reset --soft HEAD~1' 有什么区别? - What is difference between 'git reset --hard HEAD~1' and 'git reset --soft HEAD~1'? git checkout HEAD -- 之间有区别吗? 和 git reset --hard HEAD? - Is there a difference between git checkout HEAD -- . and git reset --hard HEAD? `git rm --cached`、`git reset --` 和 `git reset HEAD` 与取消暂存更改之间的实际区别是什么? - What is the practical difference between `git rm --cached`, `git reset --` and `git reset HEAD` to unstage changes? git reset --hard HEAD〜1和git revert HEAD有何异同? - What's the similarity & difference between git reset --hard HEAD~1 and git revert HEAD? `git branch -f master HEAD~` 和 `git reset HEAD~` 有什么区别? - What would be the difference between `git branch -f master HEAD~` and `git reset HEAD~`?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM