git stash
的帮助页上说
pop [--index] [-q|--quiet] [<stash>]
从存储列表中删除单个存储状态,然后将其应用到顶部 当前工作树状态的状态,即进行 git隐藏推。工作目录必须与索引匹配。
应用状态可能会因冲突而失败;在这种情况下,不是 从隐藏列表中删除。您需要手动解决冲突 然后手动调用git stash drop。
“应用状态”是否涉及三种方式的合并,或者只是将存储库修补到当前的工作树上?
这是什么类型的“冲突”?我只知道三向合并带来的冲突。
谢谢。
答案 0 :(得分:5)
“应用状态”确实是一种三元合并。
(在文档中)您在问题How is a stash entry a child commit of HEAD commit and index's commit?中指出:
祖先图看起来像这样:
.----W / / -----H----I
其中
H
是HEAD
提交,I
是记录索引状态的提交,而W
是记录工作状态的提交树。
我将把git stash pop
分解为两个组成部分,依次为git stash apply
和git stash drop
。如果套用步骤成功,则pop
也将执行drop
步骤。如果不是这样(例如,由于冲突而停止),pop
将跳过drop
。 git stash
代码目前为literally a shell script,我想说的只是一个shell脚本,但是它是一个相当大而复杂的代码,占了700多行,而the pop
code的字面意思是这样读取:
pop_stash() {
assert_stash_ref "$@"
if apply_stash "$@"
then
drop_stash "$@"
else
status=$?
say "$(gettext "The stash entry is kept in case you need it again.")"
exit $status
fi
}
如您所见,应用,如果可行,请放下;如果它不起作用,请打印一条信息行,并使用将要退出的相同状态代码退出。
I
)提交因为每个存储区至少有两个提交-I
索引状态和W
工作树状态,所以 apply 步骤可以同时应用 。在您运行git stash apply
或git stash pop
时,您选择是同时应用这两种状态,还是仅应用W
状态。如果您选择同时应用两者,则I
状态将被应用,其含义为:
git diff <hash-of-H> <hash-of-I> | git apply --cached
(尽管actual line of code稍有不同,以允许索引中包含二进制文件,并且在此之前和之后是一些相当棘手的魔术来处理各种极端情况和困难情况)。
因为这仅仅是diff | patch
,所以它不是真正的三向合并。有关其含义的详细信息,请参见What is the difference between git cherry-pick and git format-patch | git am?(Mark Adelsberger's accepted answer和my own)。无论如何,补丁可能会失败。如果确实失败,则可以选择使用git stash branch
而不是git stash apply --index
,这可以保证正常工作。
W
)提交在任何情况下,假设您要么选择忽略I
提交,要么成功应用了该提交,而Git则将结果保留下来,以便在以后的应用过程中使用,Git现在继续进行以下三个操作:您正在询问的方式合并。
这部分非常棘手。不过,它的核心是this line:
if git merge-recursive $b_tree -- $c_tree $w_tree
进行三向合并,合并基础为提交H
,--ours
提交为开始合并时索引中的值,而--theirs
提交为W
提交的内容。
注意:git merge-recursive
会尝试在开始合并时容纳工作树中的所有内容,即使它与充当ours
树的索引内容不匹配也是如此。这并不总是成功的,这就是为什么git stash pop
进入肮脏的工作树通常不是一个好主意。
如果存在合并冲突,则这三棵树-$b_tree
提交的H
,a tree that git stash
made from your index before running git merge-recursive
的$c_tree
和提交{{1 }} –正如我在my answer至Git Stash Pop - Resolve Conflicts with mergetool中所述,这是进入合并冲突暂存槽中的索引的文件的三个来源。
请注意,如果您确实使用$w_tree
进行合并,则通常会丢弃开始合并时在工作树中进行的所有未暂存的更改。这也是一个通常用不干净的工作树启动W
的原因。如果启动git mergetool
时工作树与索引匹配,则如果发生合并冲突,状态会好得多。