运行git stash两次的奇怪行为

时间:2014-10-07 20:42:34

标签: git git-stash

我的开发分支中有一些修改过的文件,很少有新创建但未被git攻击的文件。我想将这些更改移动到功能分支,因此我运行了git stash。 在用git status检查后,我意识到git没有存储未跟踪的文件。所以我跑了git stash -u

这里发生了一些奇怪的事情,因为在我检查了我的功能分支并试图查看两个存储的更改后,使用git stash show stash@{0}git stash show stash@{1},它没有显示第0个存储索引的任何内容并且第一个存储索引显示未跟踪的文件。没有第二个指数。

git stash list根本没有显示任何内容。我继续做了git stash apply并且只返回了未跟踪的文件更改,而不是修改过的文件。

应用未跟踪的文件更改后,我再次运行了git stash show stash@{0}git stash show stash@{1}。这次,第0个索引再次为空,修改后的文件更改移至第1个索引。应用存储@ {1},恢复了我的所有更改,但我无法理解存储的行为。有没有人见过这个?

1 个答案:

答案 0 :(得分:1)

为清楚起见:

$ git stash; git stash -u

这是两个单独的git stash命令。每个人都会git stash save,因为最后没有更具体的动词。

第一个git stash保存了当前索引和当前工作树(通过进行两次单独的提交,两者都不在分支上)。之后,您的索引与HEAD提交匹配,您的工作树也很干净,当然除了未跟踪的文件。

通常情况下,如果您尝试重复git stash save,它只会告诉您没有任何内容可以保存,并且什么都不做,但是对于您的第二个save,您添加了-u } flag:保存(然后删除)未跟踪的文件。所以这创建了一个第二个存储,使用您当前的索引 - 第一个save等于HEAD提交 - 和您当前的工作树 - 再次相等到HEAD提交 - 并使用第三个提交作为存储包的一部分:u提交。请参阅this answer中的图纸,但请注意,在您的特定情况下,您有两个单独的存储袋挂在同一个(HEAD)提交上。

当您使用一些活动存储保存存储时,stash脚本使用git的“reflogs”将当前存储“推送”到“存储堆栈”中,使新存储成为最重要的存储一,stash@{0}。所以你的隐藏包含u提交,此时为stash@{0},而你的存储包含修改后的索引和/或工作树(并且没有u包含未跟踪文件的提交)在stash@{1}

然后你做了:

git checkout feature

或类似于将HEAD更改为指向其他分支。我们现在通过假设存储在名为X的分支上完成来绘制情况:

... - o - o - o   <-- HEAD=feature
  \
    o - *         <-- X
        |\
        |  \
        |\   \
        i-w    \      <-- stash@{1}
                |\
                i-w   <-- stash@{0}
                 /
                u

同样,两个存储包都挂起了提交*; stash@{1}中的文件具有未跟踪的文件,但其iw提交与提交*本身相同。

你说:

  

使用git stash show stash@{0}git stash show stash@{1},它没有显示第0个存储索引的任何内容,第1个存储索引显示未跟踪的文件......

这似乎不太可能。但是,如果你写的是git show stash@{0}而不是git stash show stash@{0},而git show stash@{1}而不是git stash show stash@{1},那么就是你会看到的,因为{{ 1}}将合并提交显示为“组合差异”,您基本上要求git show查看每个存储包中的git show提交。每个w提交都是合并提交,它不是通常的合并类型,因此w会产生很大程度上无用的结果。

  

我继续执行git stash apply并且只返回未跟踪的文件更改,而不是修改后的文件。

这就是预期的结果:git show(适用git stash apply)告诉stash@{1}比较工作树和索引提交(git stash和{{1} })到他们的父(commit w),在三父stash-bag的情况下,提取第三个父(i)中的文件。 *u之间没有变化,但会带回w

  

应用*,带回了我的所有更改......

同样,这是预期的:u告诉stash@{1}将工作树(对于git stash apply)和索引提交与其父对象(git stash)进行比较。这里,更改,它会提取这些更改并将其应用于新的stash@{1}提交。此另一个存储袋中没有第三个父级,因此此时*已完成。

如果你喜欢这个结果,请继续HEAD这两个藏匿袋。