git stash apply 仅恢复未暂存的文件

git stash apply recovered only unstaged files

我在分支 A 上更改了大约 24 个文件。None 其中已提交。其中一些有变化的文件,比如 18 个是未暂存的。等6个文件上演。由于其他一些工作,我不得不结账到其他分行 B。 我在分支 A 上存储了这些更改,检出到分支 B,完成我的工作,然后又检回分支 A。 我现在做了 git stash apply。我只能看到未暂存的更改已恢复,但没有迹象表明已更改和已暂存的文件更改。

任何人都可以帮助我如何恢复这些暂存但未提交的更改?

你可以:

  • 放弃您当前的更改(例如:git checkout .),
  • 运行 git stash apply --index

当您创建存储(使用 git stash)时,git 会存储您的存储库的两个快照:您当前的索引(当前暂存文件的状态)和您当前的工作树(磁盘上文件的状态)。

当您 运行 git stash apply 时,它只恢复您的工作树的状态;当您 运行 git stash apply --index 时,它会恢复索引(就像您隐藏更改时一样)和工作树。

在您在问题中描述的情况中:您从分支 A 隐藏起来,然后又回到了 运行 宁 git stash apply 之前的状态。因此,您可以 100% 保证在应用您的存储时不会发生冲突。

--index 选项的小改动如下:如果在 运行 宁 git stash apply --index 时发生冲突,因为 git 使用索引来存储(并让你解决)冲突,你不会真正知道冲突是来自“索引”部分还是“工作树”部分。再次强调:这不适用于您在问题中描述的情况。

您需要使用 git stash apply --index。原因如下。

I have some 24 files changed on branch A. None of these are committed. Some of these files with changes, say 18 are unstaged. And other 6 files are staged.

值得指出的是:staged 只是意味着 在 Git 的索引 .

中更新

让我们进一步分解一下。 Git 提交有两个部分:

  • 任何给定 Git 提交的一部分是元数据:关于 提交的信息,例如提交人、时间等.这非常有用,但现在对您来说并不重要。

  • 该提交的另一部分是 每个文件 的已保存快照,与您(或任何人)制作时的形式一样提交。

整个提交是只读的:任何现有提交的任何部分都不能更改。此外,存储的文件 inside 提交是一种特殊的、压缩的和去重复的 Git-only 格式,只有 Git 可以 阅读。因此,不仅这些文件无法更改,您计算机上的大多数程序也无法以任何方式使用它们。这意味着在您可以 使用 提交之前,您必须 Git 提取归档文件 .

这次提取(主要)是git checkoutgit switch的内容:你告诉Git:删除我之前提取的所有文件,我是不再对 那些 文件感兴趣。转到另一个提交并提取它的文件。现在你有了可以查看使用的文件,甚至变化。这些可用的、可工作的文件位于 Git 所谓的 working treework-tree 中(另请参阅 git worktree, 自 Git 2.5).

起可用

显然,如果所有文件都有一些源存档,则每个文件必须有 两个 副本:提交中的一个(仅由 Git 并且无人可写——Git 存储它的方式,它甚至可能不是一个文件),加上你的工作树中的那个(在正常的日常形式中:一个实际的 file).但是这里有一个技巧。每个文件都有一个 third“副本”。这个额外的副本——或引号中的“副本”——采用去重格式,但是,与提交中的副本不同,可以替换.我们也应该将其称为 second 副本:第一个副本在提交中,这是每个文件的 second 副本。因为它已经删除了重复数据,所以它最初只是重新使用提交的副本。因此,工作树中的普通文件是 third 副本——它始终是 copy,因为它不在 Git-仅去重格式。

第二个副本,采用 Git 的内部格式,但可以替换,存在于 Git 所称的不同的 index 中,或者暂存区,或者——现在很少见——缓存。 (名称的最后一种形式主要显示为标志,例如 git rm --cachedgit diff --cached)。当您在工作树文件上使用 git add 时,Git:

  • 将工作树文件副本压缩为Git的内部格式;
  • 检查是否重复;和
  • 将正确的更新副本(新文件,或重新使用旧副本)放入 Git 的索引中。

当您 运行 git commit、Git 实际上 制作 来自 索引中的任何内容的提交快照当时。 这就是为什么你必须经常git add文件。你告诉Git:替换索引副本。这得到更新后的工作树复制到 Git 的索引中,准备提交。所以说 6 个文件是“暂存”的真正意思是:在下一次提交中的(比如说)400 个文件中——现在在 Git 的索引中——394 个与提交中的文件相同当前 提交,6 个与当前提交不同

说 24 个文件“未暂存”意味着:在 Git 的索引中的(比方说)400 个文件中,376 个(400 减去 24)与我的工作树中的正常格式文件相匹配, 而 24 个则没有。

请注意,由于每个文件 三个副本,因此可以同时进行 阶段性更改 (文件的索引副本 file.ext 与已提交的副本不同) 未暂存的更改file.ext 的工作树副本与未来的副本不同-提交的索引副本)。那是因为 staged change 只是意味着 HEAD-vs-index 的不同:next 提交的这个文件的副本被更新了。 Unstaged change 只是意味着索引与工作树的区别:你 可以 git add 这个文件,它会替换索引与工作树副本一起复制(Git-ified 进入下一个)提交。

git stash所做的是:

  • 保存整个索引文件集,就像在提交中一样:事实上,它确实从中进行提交,任何提交的工作方式,除了新提交不在任何分支上;然后
  • 对于 Git 索引中存在的每个文件,git add 工作树文件,并从 进行提交, 结果也是如此,除了(再次)新提交不在任何分支上;然后
  • 运行 git reset --hard.

此序列有时会因您提供给 git stash 的选项而改变,但这是主要序列:Git 在 [=71] 上进行 两次提交 =]no branch,保存索引和工作树状态,然后使用git reset --hard使索引和工作树匹配当前(HEAD)提交。

以后,当你去恢复索引and/or工作树git stash apply,你必须选择:

  • 我只想应用工作树提交,完全忽略索引提交: 这是 git stash apply。或者:

  • 我想同时应用工作树提交 索引提交: 这是 git stash apply --index.

所以Git总是保存两者,但是在apply时候你必须选择是否使用保存索引,或不。默认为“不”。