作为补充说明,请注意git stash
进行两次提交或三次提交。默认值为2;默认值为2。如果使用--all
或--include-untracked
选项的任何拼写,您将获得三个。
这两个或三个提交在一种重要的方式上很特殊:它们不在任何分支上。Git通过特殊名称查找它们stash
。1 但是,最重要的是,Git使您(并使您)完成这两个或三个提交。为了理解这一点,我们需要查看那些提交中的内容。
藏在里面的东西
每个提交都可以列出一个或多个父提交。它们形成一个图,以后的提交指向以前的提交。该存储区通常包含两个提交,我希望将它们称为i
索引/登台区域的内容以及w
工作树的内容。还要记住,每个提交都包含一个快照。在常规提交中,此快照是从索引/登台区域的内容创建的。因此,该i
提交实际上是完全正常的提交!它只是不在任何分支上:
...--o--o--o <-- branch (HEAD)
|
i
如果您要进行常规存储,则现在通过复制所有跟踪的工作树文件(到临时辅助索引)来git stash
编写代码w
。Git将此w
提交的第一个父级设置为指向HEAD
提交,第二个父级的指向设置为commit i
。最后,它设置stash
为指向此w
提交:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
如果添加--include-untracked
或--all
,则Gitu
在i
和之间进行一次额外的提交w
。的快照内容u
是未跟踪但未被忽略的--include-untracked
文件(),或即使被忽略也未被跟踪的文件(--all
)。这个额外的u
提交没有父级,然后在git stash
makes时w
,将w
的第三个父级设置为此u
提交,这样您就可以:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
/
u
在这一点上,Git还将删除在u
提交中使用的所有工作树文件(git clean
用于执行此操作)。
恢复藏匿处
当您还原存储时,可以选择使用--index
,也可以不使用它。这告诉git stash apply
(或任何内部使用的命令apply
,如pop
),它应该使用的i
承诺,试图修改当前的指数。此修改是通过以下方式完成的:
git diff <hash-of-i> <hash-of-i's-parent> | git apply --index
(或多或少;这里有很多细微的细节妨碍了基本思想)。
如果省略--index
,则git stash apply
完全忽略i
提交。
如果存储区只有两个提交,git stash apply
则现在可以应用w
提交。这是通过调用git merge
2(不允许它提交或治疗的结果为正常合并),使用原始提交在其上作出的藏匿(i
的父,并且w
第一个亲本)为合并的基础上,w
作为--theirs
提交,并且您当前的(HEAD)提交作为合并的目标。如果合并成功,那么一切都很好(好吧,至少Git如此认为),并且git stash apply
本身就成功了。如果您git stash pop
以前应用了存储,代码现在将删除存储。3 如果合并失败,则Git声明申请失败。如果你用过git stash pop
,该代码将保留存储并提供与相同的故障状态git stash apply
。
但是,如果您进行了第三次提交-如果u
您正在应用的存储中有一个提交-那就变了! 不能假装该u
提交不存在。4 混帐坚持提取的所有文件从该u
承诺,到当前的工作树。这意味着文件要么根本不存在,要么与u
提交中的内容相同。
为此,您可以git clean
自己使用-但是请记住,未跟踪的文件(是否被忽略)在Git存储库中没有其他存在,因此请确保这些文件都可以被销毁!或者,您可以创建一个临时目录,然后将文件移动到该目录中以进行保管-甚至执行另一个git stash save -u
或git stash save -a
,因为这些文件将为git clean
您运行。但这只是给您留下另一种u
样式的存储,以便以后处理。
1这是事实refs/stash
。如果您创建一个名为的分支就很重要stash
:分支的全名是refs/heads/stash
,因此它们不会冲突。但是不要那样做:Git不会介意,但是您会混淆自己。:-)
2该git stash
代码实际上git merge-recursive
直接在此处使用。由于多种原因,这是必需的,并且还具有确保在解决冲突和提交时Git不会将其视为合并的副作用。
3这就是为什么我建议回避git stash pop
,赞成的git stash apply
。您将有机会查看已应用的内容,并确定它是否实际正确应用。如果没有,您的藏身之处仍然存在,这意味着您可以用来git stash branch
完美恢复所有内容。好吧,假设缺少那个讨厌的u
提交。
4确实应该有:git stash apply --skip-untracked
或其他东西。还应该有一个变体,意味着将所有那些u
提交文件都放到一个新目录中,例如git stash apply --untracked-into <dir>
。
git stash show -p | git apply --3