如何查看 "git stash -u" 的未跟踪文件

how to view untracked files that were "git stash -u"

在 git 中存储内容非常有用。 当隐藏未跟踪文件并像这样浏览你的隐藏文件时

echo test > foo
git stash -u # foo is stashed
git stash show -p stash@{0}

不显示未跟踪的文件。 我们如何才能看到它们?

谢谢

您只需要查看第三次隐藏提交。但是“只需要”有点低估了事情,在您知道三个隐藏提交 之前,这是没有意义的。要明白我的意思,请继续阅读。

设置:有关存储的知识

当您 运行 git stash savegit stash push 时,Git 的正常操作是创建 两个 提交,两者都不其中在任何 b运行ch 上。如果你像这样绘制“之前”的图片,你将有这一系列的提交:

...--o--o--*   <-- branch (HEAD)

git stash save 完成后,您有两个 new 提交,它们不在 b运行ch branch 上,也不在任何其他 b 上运行ch 或者:

...--o--o--*   <-- branch (HEAD)
           |\
           i-w   <-- the stash

w 提交保存 work-tree 状态,而 i 提交保存索引。这两个提交中的每一个都非常像任何其他提交,事实上,i 提交是使用大多数正常的 git commit 机制进行的:Git 将当前索引写入内部索引tree object 使用 git write-tree,然后使用 git commit-tree 进行 commit object。如果你不知道这些内部 object 是什么,不要太担心:关键是这也是 git commit 完成大部分工作的方式,通过编写树和然后提交 object。 (git commit 的其余部分包括首先收集您的日志消息,并在最后更新 b运行ch 名称。)

w 提交有点复杂,因为它具有 形式 (但不是意图)的 merge commit,用两个 parents 而不是一个。但基本上它会保存 work-tree 的快照,就好像您在所有跟踪文件上都有 运行 git add

当您添加 --all--include-untracked(简称 -a-u)时,git stash 的作用是添加一个 third commit,我们可以这样画:

...--o--o--*   <-- branch (HEAD)
           |\
           i-w   <-- the stash
            /
           u

第三次提交是一个快照,但它是一个非常奇怪的快照。它包含 未跟踪的文件—untracked-but-not-ignored 文件(git stash save -u),或包括 untracked-and-ignored 个文件 (git stash save -a)。它也没有 parent 提交。

所以我们总共有 3 次提交:
i - index
w - working-tree
u - 未追踪

隐藏“堆栈”、提交哈希 ID 和 parents

一个原因1 Git 添加了 push 动词,如 git stash push——否则基本上是 [= 的同义词41=]——当你创建一个新的 stash 时,Git 使用 stash reflog 来跟踪之前的 stash。当前存储在 reflog 术语中为 stash@{0},而较早的存储变为 stash@{1}.

这些名称中的每一个都只是 Git 为您提供的更一般事物的特定情况:您可以通过 解析为正确哈希 ID 的任何名称来引用任何提交。任何提交的“真名”都是它丑陋的大哈希 ID。 The gitrevisions documentation 完整描述了将哈希 ID 拼写为 Git 的所有方法;使用 branchstash 之类的名称就是一种方式。

使用名称 stash 专门定位提交 w。 Git 然后使用 w 本身来查找提交 i,如果存在,则提交 u。 Git 可以做到这一点,因为每个提交都包含其 parent 提交的哈希 ID。使 w 具有合并提交形式的原因是它至少有两个 parent:索引提交 i 和您所在的提交 *当您首先 运行 git stash savegit stash push 时。

我们可以通过添加脱字符 ^ 字符和数字来修改大多数修订说明符(如 stash),以专门查看编号 parent。 stash^1 的写法是 commit * 的一种命名方式;写作 stash^2 是命名提交 i 的一种方式。如果提交 u 存在,写 stash^3 命名它。请注意,在某些系统 (Windows) 上,^ 可能是需要加倍或引用的特殊字符,因此您可能需要 stash^^3.[=88= 而不是 stash^3 ]


1另一个原因是添加使用路径规范进行部分存储的能力:git stash save 将任何额外参数作为消息包含在存储提交中,所以他们需要一个新的动词,使用 -m 来指定消息,为 pathspec 参数留出空间。


正在查看 u 提交

我们可以使用 git show 查看 任何 提交。对于 stash w 提交失败,因为 Git 认为 w 提交是合并,所以我们可以使用 git stash show 代替。 (它 合并,只是 git show 无法正确显示。)我的 earlier answer to a related question 要求在 [=38= 上使用 git diff ] 提交,因为在那种特殊情况下,我们不想得到 git show 显示的 header,但是如果我们只想查看未跟踪的文件提交,那么使用 git show 这里:

git show stash^3

例如。这是输出或上面的 foo 示例:

$ git show stash^3
commit 4c9bd2486706980f5a492d19c49270381db2d796
Author: Chris Torek <chris.torek gmail.com>
Date:   Sun Sep 16 12:35:03 2018 -0700

    untracked files on master: f72737e initial

diff --git a/foo b/foo
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+foo

使用像 stash@{1} 这样的名称来标识 reflog 条目 #1 中的提交,这是您的“存储堆栈”中的下一个存储。 (reflog 从零开始计数,所以 stashstash@{0} 表示相同的提交。)所以对于 stash@{1} 你需要 stash@{1}^3 或者 stash@{1}^^3.