在git中,是否有一种方法可以显示未被跟踪的存储文件而不应用该存储?

147

如果我运行git stash -u,则可以隐藏未跟踪的文件。但是,使用git stash show stash@{0}根本不显示这些未跟踪的文件。是否有方法可以在不应用stash的情况下显示隐藏的未跟踪文件?


11
2021年第二季度更新,9年后:git stash show --include-untracked 0或者git stash show --only-untracked 0可以显示未跟踪的存储文件而不应用存储。请参见下面的答案 - VonC
7个回答

178

未跟踪的文件存储在一个stash提交的第三个父提交中。虽然这并没有被正式记录,但是从引入-u功能的提交 787513 …git-stash文档中的其他描述方式等方面,这一点非常明显… 或者通过执行 git log --graph 'stash@{0}' 来查看。

您可以通过以下方式仅查看stash中“未跟踪”的部分:

git show 'stash@{0}^3'

或者,只需通过以下方式获取“未跟踪”的树本身:

git show 'stash@{0}^3:'

或者,通过以下方式访问树中的特定“未跟踪”文件:

git show 'stash@{0}^3:<path/to/file>'

很遗憾,没有一种好的方法可以得到所有暂存 + 未暂存 + 未跟踪文件与“当前”状态之间差异的摘要。例如:git show 'stash@{0}' 无法包括未跟踪文件。这是因为藏匿提交本身的树对象,即stash@{0}:,不包括第三个“未暂存”父级的任何更改。

这是由于藏匿的重新应用方式:跟踪的文件可以轻松地应用为补丁,而未跟踪的文件理论上只能作为“整个文件”应用。


正如你所说,我还没有找到一种方法来获取一个存储库的单个摘要视图,但是你可以使用一个命令查看其完整信息:git log --graph --topo-order -m -u。http://matthewlmcclure.com/s/2014/01/10/git-how-to-see-untracked-stashed-files-without-apply.html - Matt McClure
5
请注意,如果您在那个存储堆栈中实际上没有未跟踪的文件(但认为您有),则会出现丑陋的错误( fatal: ambiguous argument 'stash@{0}^3': unknown revision or path not in the working tree.)。 - Randall
2
@antak:错了,git stash show不会显示未跟踪的文件(至少对于 git 2.7.4 是这样)。 - Norbert Bérci
2
注意(2.13.2-linux): git stash pop 将首先尝试恢复未跟踪的文件,然后尝试恢复已跟踪的文件。如果后者操作失败(例如冲突),则不会回滚第一个操作(未跟踪文件存储状态将保持不变,但文件不会从磁盘中删除),因此即使您修复了冲突,下一次弹出仍将失败。 - Marinos An
1
在某些 shell 环境中,^ 是一个通配符字符。我(使用 zsh 和 _zimfw_)必须像这样转义它:git show stash@{0}\^3 - einjohn
显示剩余7条评论

28

您可以使用以下命令列出所有存储的提交:

``` git stash list ```

git rev-list -g stash

由于储藏被表示为HEAD、索引和没有父级的“根”提交的三方合并提交,因此可以通过将上述输出导入以下内容来列出未跟踪文件储藏:

git rev-list -g stash | git rev-list --stdin --max-parents=0

以上内容的有用应用:

仅显示未跟踪、被藏起来的文件

git rev-list -g stash | git rev-list --stdin --max-parents=0 | xargs git show --stat

当然,如果要查看文件内容,删除--stat即可。

查找特定文件

git rev-list -g stash | xargs -n1 git ls-tree -r | sort -u | grep <pattern>

查找未被跟踪的文件

git rev-list -g stash | git rev-list --stdin --max-parents=0 | xargs git grep <pattern>

列出所有隐藏储藏的内容

git rev-list -g stash | git rev-list --stdin | xargs git show --stat

谢谢!当我使用“查找特定文件”命令时,例如我会得到:100644 blob 05e25619a6f2649b7d635b5aa897cbfc68a4f15d widget/app.css。现在我该如何弹出这些更改呢?(我不确定它在哪个存储区) - John Smith
1
那个哈希值是针对文件对象(blob)的,所以你可以使用 git show 05e25619a6f2649b7d635b5aa897cbfc68a4f15d > widget/app.css。 (当然,widget/ 目录必须存在,因此它不像使用路径规范的 git checkout 那么方便。) - Steve

17
然而,使用git stash show stash@{0}命令时,这些未跟踪的文件根本不会显示出来。
注意:自Git 2.11版本(即2016年第四季度,此问题发布后的4年),您只能通过索引引用stash。
git stash show 0

由于git stash被重写为C语言,导致了一个更近期的错误,已在Git 2.22中修复(2019年第二季度)。

有没有办法在不应用stash的情况下显示未跟踪的存储文件?

是的,有办法了,从Git 2.32开始(2021年第二季度,OP发帖后的9年)。

git stash show --include-untracked

# or
git config --global stash.showIncludeUntracked true
git stash show

"

"git stash show"(man) 学会了可选择显示存储的未跟踪部分。

查看提交 0af760e提交 d3c7bf7(2021年3月3日)由Denton Liu (Denton-L)完成。
(由Junio C Hamano -- gitster --提交 f5c73f6中合并,2021年3月22日)

stash show: 教授 --include-untracked--only-untracked 签名:Denton Liu 可以使用未跟踪的文件创建存储项,方法是通过git stash push --include-untracked(man)命令。
然而,由于未跟踪的文件存储在存储项的第三个父项中而不是存储项本身,因此运行git stash show(man)命令时,差异中不包括未跟踪的文件。
使用--include-untracked选项,除了在存储项的基线和工作树之间有修改的路径外,还会显示记录在第三个父项(如果存在)中的未跟踪路径。
可以手动创建格式错误的存储项,其中存储项中的重复未跟踪文件将掩盖已跟踪的文件。
我们通过自定义的unpack_trees()回调函数stash_worktree_untracked_merge()来检测并报错。
此外,还可以使用--only-untracked选项来仅显示存储项的未跟踪文件。
这类似于git show stash^3(man),但提供一个方便的抽象,使用户不必考虑底层实现细节。

git stash现在在其手册页面中包含了:

'git stash' show [-u|--include-untracked|--only-untracked] [<diff-options>] [<stash>]

git stash现在在其man page中包含以下内容:

--no-include-untracked

当与pushsave命令一起使用时, 所有未跟踪的文件也会被暂存,然后通过git clean进行清理。

当与show命令一起使用时,将未跟踪的文件作为差异的一部分显示在暂存条目中。

--only-untracked

此选项仅适用于show命令。
仅显示暂存条目中未跟踪的文件作为差异的一部分。


而且你还有一个配置与这些新选项相匹配:

stash show:了解 stash.showIncludeUntracked

签署者:Denton Liu

之前的提交教会了git stash show --include-untracked(man)
用户可能希望能够始终启用--include-untracked行为。
教授stash.showIncludeUntracked配置选项,使用户可以以类似于stash.showPatch的方式实现此目的。

git config现在在其man page中包含以下内容:

stash.showIncludeUntracked

如果将其设置为true,则不带选项的git stash show命令将显示存储条目的未跟踪文件。

默认值为false。

git stash现在在其man page中包含以下内容:

您可以使用stash.showIncludeUntrackedstash.showStatstash.showPatch配置变量来更改默认行为。


在Git 2.32(2021年第二季度)中,处理最近添加到 "git stash show"(man) 的选项的代码,在对不记录未跟踪部分的存储条目使用这些选项时发生了段错误

参见 提交 1ff595d提交 aa2b05d(2021年5月12日)由Denton Liu (Denton-L)提交。
(合并者:Junio C Hamano -- gitster --,于提交 a8a2491,2021年5月16日)

stash show: 修复使用 --{include,only}-untracked 时的段错误问题 签名:Denton Liu 当运行git stash show --include-untracked(man)git stash show --only-untracked(man)命令时,如果存储的内容中不包含未跟踪的条目,将会导致段错误。

这是因为我们没有检查未跟踪的条目是否实际存在,而是盲目地尝试解引用它。

在尝试解引用之前,请确保未跟踪的条目确实存在。

查看 commit af5cd44(2021年5月21日)由 Denton Liu (Denton-L) 提交。
(由 Junio C Hamano -- gitster -- 合并于 commit 378c7c6,2021年5月22日)

stash show:即使给出了diff选项,也要使用stash.showIncludeUntracked Signed-off-by: Denton Liu
如果git stash show(man)提供了有关如何显示差异的选项,该命令将忽略stash.showIncludeUntracked配置变量,并默认不显示任何未跟踪的文件。
这是一个不直观的行为,因为差异输出的格式和是否显示未跟踪的文件是无关的。

即使给出了差异选项,也要使用stash.showIncludeUntracked
当然,这仍然可以通过命令行选项进行覆盖。

更新文档,明确说明在给出差异选项时将覆盖哪些配置变量。

git config现在在其man page中包含以下内容:

如果设置为truegit stash show命令将显示存储项的未跟踪文件。

默认值为false

git stash现在在其man page中包含以下内容:

如果未提供<diff-option>,则默认行为将由stash.showStatstash.showPatch配置变量确定。

您还可以使用stash.showIncludeUntracked来设置是否默认启用--include-untracked


1
注意:截至2021年5月3日,--include-untracked还没有被正式纳入任何一个git版本中,它目前只存在于master分支中。请关注此提交的信息头底部出现的与master相对应的发布标签:https://github.com/git/git/commit/d3c7bf73bdb679dd98c6aff65edbce4df743ddd3以上是一个很好的答案,一旦这个提交被接受,它就值得所有点赞。 - timoxley
@timoxley同意:这是针对Git 2.32(2021年第二季度)的。 - VonC
@EmmanuelTouzery 的确。我在这个回答中也提到了这个选项。 - VonC
1
@EmmanuelTouzery 我终于在答案中包含了你的评论! - VonC
1
@EmmanuelTouzery 我终于把你的评论包括在答案中了! - undefined
显示剩余3条评论

16

列出暂存区中未跟踪的文件:

git ls-tree -r stash@{0}^3 --name-only

展示所有未被追踪的文件的完整差异(包括内容):

git show stash@{0}^3

这些命令读取最近的一个stash。要查看早期的stash,请将"stash@"后面的数字递增,例如stash@{2}表示倒数第二个stash。

这样做的原因是git stash为每个stash创建了一个合并提交,可以用stash@{0}stash@{1}等来引用。该提交的第一父项是stash时的HEAD,第二个父项包含已跟踪文件的更改,第三个父项(可能不存在)包含未跟踪文件的更改。

这在“Discussion”章节的手册中有部分解释。


6
为了查看存储区中的所有文件(包括已跟踪和未跟踪的文件),我在我的配置文件中添加了这个别名:
showstash = "!if test -z $1; then set -- 0; fi; git show --stat stash@{$1} && git show --stat stash@{$1}^3 2>/dev/null || echo No untracked files -"

需要一个参数来指定您要查看的存储库。请注意,它仍将呈现为两个背靠背的列表。

if...fi部分更改bash参数 $1为0(如果没有传递参数)。


6
一个解决方法:在隐藏文件之前先将其放置在暂存区,这样git stash show -p命令就能按预期工作。
git add .
git stash save

注意: 这个方式可以添加交互部分,这里是具体步骤
注意: 确保您没有先前暂存的工作内容,否则您将无法区分它们。
这可能会有所帮助。


0

我在2.32版本的git下遇到了一个问题,无法找到并应用正确的存储库来处理未跟踪的文件。

我使用了以下命令来查找带有未跟踪文件和日期的存储库:

git rev-list -g stash | git rev-list --stdin --max-parents=0 | xargs git show --stat

在我使用另一个命令显示按日期排序的藏匿列表以查找特定日期的正确藏匿位置后:

git stash list --date=local

之后,我再次使用git stash list来查找存储的名称,并使用git stash apply应用它。

这对我有用。我希望这对其他人也有用!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接