对比一个存储区与Git中的差异

1837

我怎样能够查看取消暂存所做的更改会对当前工作树产生什么影响?在应用更改之前,我想知道将会进行什么更改!


16
可能是Is it possible to preview stash application in git?的重复问题。 - quazgar
1
相关帖子请点击此处 - RBT
你可能还对tig的存储视图感兴趣。 https://jonas.github.io/tig/doc/manual.html - undefined
15个回答

2524

查看最新的stash:

git stash show -p

查看任意stash:

git stash show -p stash@{1}

来自git stash的手册:

默认情况下,该命令显示diffstat,但它将接受git diff已知的任何格式(例如,git stash show -p stash@{1}以补丁形式查看第二个最近的存储)。


82
stash@{0} 是默认值;只有当你想查看之前的暂存时才需要提供参数。 - Cascabel
59
好的。我只是提供它,以便清楚如何查看除“{0}”之外的其他存储。 - Amber
107
这不会显示储藏内容和当前工作目录之间的差异,而是显示储藏内容和其原始父级之间的差异,对吗?根据手册:"显示以储藏状态和其原始父级之间的差异作为记录在储藏中的更改。" - Magne
18
@Amber - 是的,尽管如果您当前的工作树是脏的,这很重要,并且使它变得有些复杂。我从这个角度来看待它,并在下面的答案中分享了一个过程。 - Magne
21
"-p" 代表什么意思? - Gerald
显示剩余13条评论

424

查看最近的暂存内容:

git stash show -p
看到任意存储内容:
git stash show -p stash@{1}

另外,我使用git diff将暂存区与任何分支进行比较。

你可以使用:

git diff stash@{0} master

查看与主分支相比的所有更改。


或者您可以使用:

git diff --name-only stash@{0} master

为了轻松查找仅更改的文件名。


14
这并没有回答具体问题。如果您从主分支创建了存储(以便稍后保存工作),然后对主分支进行一些提交以进行其他工作,然后执行 git diff stash@{0} master,则会得到一个针对当前主分支的存储差异(其中包括在制作存储后在主分支上完成的工作),而不是存储将更改的文件/行,这正是该问题所涉及的内容。 - Tom De Leu
66
即使你没有回答确切的问题,我很高兴你回答了这个问题。这提供了更多的信息,知道如何在分支之间获取差异非常棒。我也喜欢学习“--name-only”标志 :) - Rebekah Waterbury
9
这还允许使用自定义的差异查看器来查看差异,例如: git difftool --tool=... stash@{0} HEAD - Andre Holzner
12
很好的观察和重要的观点。用它的父项比较一个存储项,这似乎可以运行:git diff stash@{0}^ stash@{0} - erikprice
2
另外,您可以添加文件名 git diff stash@{0} master -- filename 以获取特定文件的更改。 - David
显示剩余3条评论

135

如果您的暂存更改所基于的分支在此期间发生了更改,则此命令可能会有用:

git diff stash@{0}^!

这将比较储藏与其基于的提交。


太好了,我在~/.gitconfig中添加了一个别名:laststash = diff stash@{0}^! - sbeam
10
完美组合:git difftool stash^! 用于比较最后一个储藏与其所基于的提交之间的差异, git difftool stash HEAD 用于比较最后一个储藏与当前提交之间的差异(对于以前的储藏使用 stash@{n})。 - ChrisV
"git diff stash@{0}^!" 简化为 "git diff stash@{0} ^stash@{0}1 ^stash@{0}2 ......",但由于 git diff 只接受两个提交,它显示的是 stash@{0} 和 ^stash@{0}~1 之间的差异,并且忽略了第二个提交开头的 ^,因此没有任何区别。 - Naga Kiran
1
你在用哪个shell?我的需要引用它:git diff 'stash@{0}^!' - trusktr
显示剩余4条评论

80

根据您想将存储区与哪个内容进行比较(本地工作树/父提交/HEAD提交),实际上有几个可用的命令,其中包括古老的git diff和更具体的git stash show

将stash与以下内容进行比较↓ git diff git stash show
本地工作树 git diff stash@{0} git stash show -l
父提交 git diff stash@{0}^ stash@{0} git stash show -p
HEAD提交 git diff stash@{0} HEAD /

虽然git stash show在第一眼看上去更易于使用,但git diff实际上更强大,因为它允许指定文件名以获得更专注的差异。我个人已经在我的zsh git插件中为所有这些命令设置了别名。


3
这是唯一正确的答案(至少在 git 2.17.1 版本中是如此)。这是唯一包含“git stash show -l”以及更多信息的答案。非常感谢您发布它 - 我们如何将其投票置顶?在最顶部的评论中发表评论即可。 - Starman
2
当我运行 git stash show -l 时,出现了 error: switch 'l' requires a value 的错误。 - mmmm
2
在较新版本的git中,“-l”选项已不再有效。 - Matthew Thomas
1
根据您的shell(例如PowerShell),您可能需要将带有花括号的参数放在引号内(例如git diff "stash@{0}")。 - Matthew Thomas

55
如果您的工作树处于脏状态,您可以先提交脏工作树,然后将其与stash进行比较。之后,您可以撤销带有脏工作树的提交(因为您可能不想在提交日志中记录该脏提交)。
您也可以使用以下方法相互比较两个stash(在这种情况下,您首先弹出其中一个stash)。
  • 提交您的脏工作树:

git add .
git commit -m "Dirty commit"
  • 将暂存区与该提交进行差异比较:

  • git diff HEAD stash@{0}
    
  • 然后,之后您可以将提交还原,并将其放回工作目录:

  • git reset --soft HEAD~1
    git reset .
    
    现在你已经将脏的工作树与你的藏匿比较,并回到最初的状态。


    有没有一种方法可以只查看存储内容所更改的文件的差异? - lagweezle
    1
    在2020年,这要简单得多;请查看我的最新答案。 - David Deprost
    1
    有趣,我不知道 git stash show -l。它是否将最新的存储与工作(脏)副本进行比较?如何在不出现 error: switch l requires a value 的情况下使用它? - Magne
    是的,确实会针对(可能是脏的)工作副本进行差异比较。您只需输入git stash show -l即可使用它。至于为什么它对您无效,我只能猜测您可能正在使用旧版本的git?我正在使用git v2.20.1,并且它可以无误地运行。 - David Deprost

    36

    @Magne的答案是截至目前为止回答该问题最灵活/有用的解释,但它比必要的要复杂得多。与其提交并重置,不如将您的工作副本保存,进行比较,然后取消保存。

    git stash save "temp"
    git diff stash@{0} stash@{1}
    git stash pop
    

    这向你展示了把工作区的变化临时变成存储堆栈顶部(stash@{0}),把原来的顶部往下移动一个位置(stash@{1}),然后使用原始顶部在“新集合”位置进行比较,以便您看到将其应用于当前工作的变化。

    “但如果我没有任何当前工作呢?” 那么你就是一般无聊的情况。只需使用 @Amber 的答案即可。

    git stash show
    

    或者 @czerasz 的答案

    git diff stash@{0}
    

    或者承认,将变更存储和取消存储都是快速且容易的,只需要取消存储变更并检查它们。 如果您暂时不需要它们,就将它们(当前索引/工作文件夹中的变更)舍弃。全部内容如下:

    git stash apply
    git diff
    git reset
    git checkout
    

    3
    这种简单的方法(将暂存区内容进行储藏,再与另一个储藏做比较)既安全又易于理解。对于某些情况下,您可能希望使用 git stash save -u 命令来储藏未跟踪的文件。 - mleonard

    26

    以防万一,比较工作区和stash中的文件,请使用以下命令

    git diff stash@{0} -- fileName (with path)
    

    20

    在Git版本1.8.5.2上,这对我有效:

    git diff stash HEAD
    

    2
    误导性的!问题是:我如何查看取消隐藏操作对当前工作树所做的更改?这将显示存储和HEAD之间的差异,这可能与使用git stash apply应用的内容非常不同。 - MikeJansen
    请仔细阅读问题:“在应用更改之前,我想知道会有哪些更改!” 我会快速回答这个问题。 - yerlilbilgin
    另外,您可以看到所有其他答案都与将当前头(或工作集)与存储区进行差异处理有关。为什么只有我的答案是误导性的?这不公平。 - yerlilbilgin
    @yerlilbilgin 请看我在您下面的回答。 - MikeJansen
    我们可以省略 HEAD,因为它默认存在,不是吗? - Al.G.

    10

    如果你有用于比较差异的工具(如Beyond Compare)

    git difftool stash HEAD
    

    1
    误导性的!问题是:我如何查看取消隐藏操作对当前工作树所做的更改?这将显示存储和HEAD之间的差异,这可能与使用git stash apply应用的内容非常不同。 - MikeJansen
    1
    如果您认为这是误导性的,请检查所有其他答案。那不公平! - yerlilbilgin
    1
    请注意,我将同样的评论复制到了另一个误导性的答案中(基本上是相同的答案)。已经有类似评论的其他答案我就不管了。如果您了解git stash的工作原理,那么您将意识到diff'ing存储与HEAD不是所应用的内容(这是OP所问的)。实际的“stash”是存储提交与之前提交的差异。然后将此补丁应用于HEAD。因此,如果您想知道OP所问的内容,您必须显示存储和之前提交之间的差异,这些正确的答案已经做到了。 - MikeJansen
    1
    这个回答比其他(不必要的)长回答更直接地回答了问题,并且完全符合OP的要求,除了删除HEAD。 我可以修改@yerlilbilgin的答案以删除HEAD,但我认为任何使用git的人都可以找出这部分内容,而我增加答案的长度会使它难以阅读。 对@yerlibilgin没有责备。 - Sridhar Sarnobat

    10
    我认为git diff <current-branchname>..stash@{0}是比较本地工作树和最近的stash之间更改的最直观的方法。根据需要将stash@{0}替换为适用的stash编号。

    请注意,git diff stash@{0}可能会产生误导性的结果。如果您的stash和当前分支的两个历史记录发生了分歧,则差异将看起来像您正在添加所有新的内容到您的stash并删除当前分支中唯一的所有内容。

    基于git book的答案

    此外,请注意双点..和三点...指定不同的提交比较,我在此回答中指的是双点。有关详细信息,请参见git书籍


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