作为补充说明,请注意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 stashmakes时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 merge2(不允许它提交或治疗的结果为正常合并),使用原始提交在其上作出的藏匿(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