`git stash show -p stash @ {N}`和`git show stash @ {N}`之间的区别?

时间:2014-02-12 20:11:19

标签: git git-stash git-show

我认为它们应该基本相同,但是当我尝试时

$ git stash show -p stash@{N}

$ git show stash@{N}

后者显示了一些额外的提交信息,但实际差异要短得多。 (前者显示了大约十二个文件,但后者只显示了一个。)

那么,这两者究竟有什么区别,为什么它们不同呢?

我还可以依赖git diff stash@{M} stash@{N}之类的东西来正确吗?

2 个答案:

答案 0 :(得分:19)

藏匿袋

git stash保存的内容是我调用"stash bag"所采用的内容。它由两个 1 单独的提交组成:"索引"提交(暂存区域)和工作树"承诺。工作树提交是一种有趣的合并提交。

让我在这里再次绘制它(参见更长版本的参考答案),只是为了正确说明它。为简单起见,我们假设您只有一个小型仓库,只有一个分支和三个提交,AC。您在一个分支上进行了一些更改,然后运行git stash save(或仅仅git stash)。这就是你得到的:

A - B - C     <-- HEAD=master
        |\
        i-w   <-- the "stash"

现在你可以制作(或切换到)另一个分支,但是为了说明,我们只是说你把那个藏在那里然后做更多的&#34;定期&#34;提交master

A - B - C - D - E    <-- HEAD=master
        |\
        i-w   <-- stash

这里的重点是&#34; stash-bag&#34;,这对i ndex和w ork-tree提交仍然挂在同一个提交中之前。提交无法更改,对于stash-bag提交也是如此。

但现在您通过进行一些更改(同时仍然在master上)并再次运行git stash save来创建藏匿。

旧的藏匿袋怎么了? &#34;引用名称&#34; 2 stash现在指向 new 隐藏包。但旧的存储袋提交仍在那里。他们现在需要一个&#34; reflog&#34;样式名称stash@{1} 3

无论如何,你现在拥有的是:

A - B - C - D - E     <-- HEAD=master
        |\      |\
        i-w     i-w   <-- stash
          .
           -------------- stash@{1}

(当你使用git stash drop时,隐藏脚本只是操纵stash引用的reflog来删除丢弃的存储包的ID。这就是为什么所有&#34 ;更高的&#34;得到重新编号。实际的存储袋本身是在下一个git gc上收集的垃圾。)

下一步是理解正在发生的事情的关键。

任何时候git都需要你命名一个特定的提交,你可以用很多不同的方式来做。

每个提交都有一个&#34;真实姓名&#34;这是你看到的丑陋的SHA-1哈希值,如676699a0e0cdfd97521f3524c763222f1c30a094。你可以这样写。它总是意味着相同的提交。提交永远不会被更改,并且它是提交的全部内容的加密哈希,因此如果存在该特定提交,则该值始终是其名称。

但是,这对人们来说并不是一个好名字。所以我们有别名:分支和标记名称,以及HEADHEAD~2等相对名称,以及HEAD@{yesterday}master@{1}等reflog样式名称。 (有&#39; sa命令,git rev-parse,将这样的名称字符串转换为哈希值。尝试一下:运行git rev-parse HEADgit rev-parse stash,依此类推.Git中的大多数内容都使用git rev-parse或其大哥,可以执行更多操作git rev-list,将名称转换为SHA-1值。)

(有关如何命名修订版的完整说明,请参阅gitrevisions。Git使用SHA-1不仅仅是提交,但这里我们只考虑提交。)

Git stash show,git show和git diff

好的,最后,我们可以访问您的git show vs git stash showgit diff等等。让我们首先处理git stash show,因为那是所谓的用于存储的人。此外,git stash子命令将验证您命名的提交 - 或者,如果您没有提交提交,则通过stash引用找到的提交 - &#34;看起来像&#34;存储,即,这些有趣的合并提交之一。

如果你运行git stash show -p,git会显示差异(-p atch)。但究竟是什么表现出来?

使用藏匿袋返回图表。每个存储包都挂起特定的提交。以上,&#34;主要&#34; stash现在悬挂在提交E之前,而stash@{1}之前的存储暂停于C

git stash show -p做的是将存储的工作树提交w与存储挂起的提交进行比较。 4

你当然可以自己做。假设您要比较w中的stash(挂起提交E)与提交E,后者可以通过分支名称进行命名master。所以你可以运行:git diff master stash。这里名称stash引用(当前)隐藏提交wmaster引用提交E,因此这将生成与git stash show -p stash完全相同的补丁。 (并且,如果您想将w中的stash@{1}与提交C进行比较,则只需运行git diff,以便为这两个提交命名。当然,&# 39;更容易git stash show -p stash@{1}。) 5

普通git show怎么样?这有点复杂。 git show很高兴显示提交,并为您提供了stash引用(stash本身或其中一个reflog变体)。这是一个有效的提交标识符,它解析为其中一个存储包中的w工作树提交之一。但git show在看到合并提交时的行为方式不同。正如文档所说:

  

它还以git diff-tree --cc生成的特殊格式显示合并提交。

所以git show stash@{1}向您显示&#34;组合差异&#34;,假设提交w是提交Ci的正常合并,生成{ {1}}。毕竟它不是普通的合并,尽管合并的diff 可能实际上是有用的,只要你知道你在看什么。阅读w下的--cc文档,详细了解其工作原理,但我要注意git diff-tree隐含--cc,其中包含此位:

  

...仅列出从所有父母修改的文件。

对于-c,如果您在运行stash之前已经git add - ed文件,那么git stash - vs - {{1 diff是空的,你不会在输出中看到那些文件。

最后,如果您i:这只是要求w比较不同的git diff stash@{M} stash@{N} ork-tree提交。具有多少意义取决于您的比较,这通常取决于存放袋的附着位置。


1 两三个,真的,但是我要把它画成两个。您可以使用git diff(或普通w进行两次提交,这意味着git stash save)。如果添加git stashgit stash save选项以保存未跟踪或所有文件,则会收到三次提交。这会影响存储恢复,但不会影响-u命令的输出。

2 A&#34;参考名称&#34;只是一个名称,而不是分支或标签名称。有许多可能的参考名称形式。分支和标签只是具有特殊用途的名称。 &#34;远程分支&#34;是这些参考文献的另一种形式,&#34; stash&#34;也是一个参考。

事实上,-a只是另一个参考,尽管它是非常特殊参考。我非常重要,如果您删除git stash show文件,git将决定您的存储库不再是存储库。

对于一些特殊情况例外 - HEADHEADHEAD等等,引用都以字符串ORIG_HEAD开头。分支以MERGE_HEAD开头,标签以refs/开头,&#34;远程分支&#34;从refs/heads/开始。换句话说,引用具有名称空间&#34;,通常以refs/tags/开头,然后在其下面添加另一个单词以标识它们的居住地。

隐藏参考拼写为refs/remotes/(并停在那里,没有refs/或类似的东西)。

3 事实上,这真的 使用了reflog。除其他外,这意味着除了&#34; main&#34;之外的其他东西。一,refs/stash可以过期。 (幸运的是,作为musiphil notes,git 1.6.0的默认值是这些不要到期;你必须为它们配置到期时间才能实现这一点 - 这可能不是无论如何你想要什么。)

4 聪明的方式它使用后缀refs/stash/jimmy_kimmel表示法,在我的other answer中拼写出来。

5 如果您想查看这些藏匿袋中的refs/stash ndex-commits怎么办?啊,好问题! :-)存储脚本没有一个很好的答案。查看这些内容的简单方法是使用^后缀来命名每个存储的第二个父级,即i提交。并且,如果你有第三个提交包含未跟踪或所有文件的存储,那就是第三个父:提交^2看起来像三父合并而i得到第三个。但同样,w不是正常的合并,所以它很棘手。查看存储的所有部分的最简单方法可能是使用stash^3将其转换为自己的独立分支。

答案 1 :(得分:2)

我认为这是因为git存放了工作目录的一个怪癖。索引分开。 git stash show -p stash@{N}将显示存储中的所有更改,包括添加到阶段的更改。但是,git show stash@{N}不会包含在存储之前已暂存的更改。似乎git stash命令足够聪明,可以将它们组合在一起,而git show只是向您显示blob的内容stash@{0}

是的,git diff stash@{M} stash@{N}将按预期工作。