找到一个特定的藏品我该如何展示它?

Found a specific stash how do I show it?

通过以下命令,我找到了一个包含某个未跟踪文件的存储区:

git rev-list -g stash | xargs -n1 git ls-tree -r | sort -u | grep widget

这条命令returns:

100644 blob 05e25619a6f2649b7d635b5aa897cbfc68a4f15d widget/app.css

我现在如何显示这个藏品?

我试过了:

git stash show -p stash@{100644}

返回了什么 stash@{100644} is not a valid reference

谢谢

就这样:

git show 05e2561

存储仅使用常规 git 提交,就像其他任何提交一样。

编辑:

正如 OP 在评论中提到的那样,上面的命令只显示了一个 blob,而不是一个提交。

我现在唯一的想法是:

git stash list

获取存储中所有提交哈希的列表。然后对于每个提交哈希,执行:

git show --name-only abcd1234

替换实际的提交哈希。我确定可以编写 shell 脚本来自动执行此操作。

但正如我在评论中所说,如果您有大量的存储提交,并且您正在使用存储进行 long-term 存储,那么您就做错了 git。您需要学习如何使用分支,或者您可能需要做的只是更频繁地提交 master

请问,为什么使用 stash 而不是 commit? stash 只是幕后的提交,但经过伪装并变得更加复杂。我经常使用 git 从不 使用 stash。如果我需要保存工作并处理其他事情,我只是进行正常提交。

如果您必须使用 stash,它应该仅供非常 short-term 使用,同时您可以节省您的工作以处理另一项任务。你的储藏室应该几乎总是空的。

如其他答案所述:100644 不是提交哈希,也不是隐藏编号。您构建的命令实际上不会跟踪生成此特定 ls-tree 条目的提交 ID。

如果你想找到包含文件 widget/app.css 的隐藏文件,例如:

# if you have more than 50 stashes, replace '50' with a number big enough
for i in {0..50}; do
    if git rev-parse --verify -q stash@{$i}:widget/app.css; then
        echo "stash@{$i}"
    fi
done

考虑使用这个(未经测试):

git log -g stash --format='%H %gD' |
while read hash rel; do
    git ls-tree -r $hash | sed "s:^:$rel :"
done |
grep widget

说明

注意:

git rev-list -g stash | xargs -n1 git ls-tree -r | sort -u | grep widget

不会产生相当您想要的输出。你得到了:

100644 blob 05e25619a6f2649b7d635b5aa897cbfc68a4f15d   widget/app.css

这是 git ls-tree -r 输出中的一行。这些输出行的格式是 mode type hashtabpath(with文字制表符)。 mode,在本例中为 100644,来自一组有限且固定的可能性:100644 表示 blob 即不可执行。 (type 字段由模式决定,因此它是多余的。)blob 的 hash 是blob的hash ID:事实上,除了160000,它被称为commit,代表一个gitlink,hash总是一些内部的Git此存储库中的对象哈希。 None 其中曾经是隐藏提交哈希 ID 或相对编号。也就是说,其中 none 可以作为 stash@{<em>number</em>}.

如果我们 return 到 git rev-list -g stash 命令,这将简单地遍历 stash reflog。它与 运行ning git reflog stash 相似,除了它不是以下形式的输出:

<hash> stash@{0}: <subject>
<hash> stash@{1}: <subject>
  .
  .
  .

它只生成哈希 ID。因此 git rev-list 的输出包含您想要打印的信息。但是该输出进入 xargs -n1 git ls-tree -r,因此 xargs 吃掉输出并将其提供给 git ls-tree -r,后者将其吃掉并且不再打印出来。

然后,要获得所需的信息,您需要修改或替换 xargs 命令。允许您实现目标的修改是在每个 git ls-tree -r 行的左侧打印提交哈希 ID and/or stash-relative 名称。

要获得 stash-relative 名称,更改或替换 git rev-list 输出可能是明智的。不幸的是 git rev-list --format='%H %gD',这是处理这个问题的合乎逻辑的方法,但不起作用。我们必须使用 git log,它有一个缺陷:git log 是一个 porcelain 命令而不是管道命令,因此它服从用户配置,这可能会改变它的行为.1 但我们对此无能为力,所以我们不妨继续努力。


1在我看来 git log 需要一个 --porcelain 标志 la git status,尽管我一直想知道为什么这flag 拼写为 --porcelain 而不是 --plumbing.


替代序列

我们将从:

开始
git log -g stash --format='%H %gD'

和 运行 它的输出通过一个将获取哈希的命令,使用 git ls-tree -r 列出哈希在左侧的提交的全部内容,并在每一行前加上 reflog-relative %gD 输出和一个 space。我们将为这些使用普通的 sh 编程结构,尽管这会有点慢:

git log -g stash --format='%H %gD' |
while read hash rel; do
    git ls-tree -r $hash | sed "s:^:$rel :"
done

在这里,我们 运行 git ls-tree -r 对散列进行处理,并将其输出通过 sed、stdin-stream 编辑器进行管道传输。编辑命令是用相对引用替换行首(^)。我们可以使用冒号 : 字符作为分隔符,因为我们知道任何分支名称中都不能出现冒号。2 这意味着扩展 $ref 不会意外触发一个 end-of-delimiter 序列。我们对 sed 命令参数使用双引号,以便 $ref does 得到扩展,并且加上 shell 的 while read 循环结构——解释整个循环。

我们可以删除 sort -u,因为没有理由对这些进行排序,并且 uniq-ing 每一行似乎没有效率,但我们仍然希望最终的 | grep widget 到这个小 git log | while one-liner 到一个解决方案中,该解决方案查找包含将匹配 widget 的任何路径字符串的存储,例如 stowidgetname(Stow ID,Get Name)。


2冒号不是唯一的选择;参见 the git check-ref-format documentation。然而,冒号在视觉上是有区别的并且 non-problematic。通常的斜杠定界符通常是一个糟糕的选择,因为引用日志名称可能包含斜杠。在我们的特定情况下,我们知道 ref 名称是 stash,它不包含斜杠,但是使用适用于其他名称的东西是很好的,我们应该尝试重新使用这个扩展的 one-line脚本。 $rel 作为 reflog-relative 扩展,将是引用名称后跟 @{ 后跟一系列数字后跟 },所以 @{} 和数字以及任何有效 ref-name 个字符都是 错误 个选择。一般来说,控制字符是不好的选择,因为它们很难被看到。这使得规则 4 中的 space、波浪号、插入符号和冒号成为显而易见的候选者。插入符是我们的 beginning-of-line 字符,所以这是一个糟糕的选择,而 space 在视觉上是模糊的,所以我们只使用波浪号和冒号。我选了冒号