Git diff 与 stash

Posted

技术标签:

【中文标题】Git diff 与 stash【英文标题】:Git diff against a stash 【发布时间】:2011-12-02 10:14:21 【问题描述】:

如何查看取消存储对当前工作树所做的更改?我想知道在应用之前会进行哪些更改!

【问题讨论】:

Is it possible to preview stash application in git? 的可能重复项 相关帖子here. 【参考方案1】:

查看最近的存储:

git stash show -p

查看任意存储:

git stash show -p stash@1

来自git stash 联机帮助页:

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

【讨论】:

stash@0 是默认值;如果你想查看以前的存储,你只需要一个参数。 对。我只是提供了它,以便清楚如何查看除0 之外的其他存储。 这不会显示 stash 和当前工作目录之间的差异,而是显示 stash 和它的原始父级之间的差异。正确的?来自手册页:“将存储中记录的更改显示为存储状态与其原始父级之间的差异。” @Amber - 没错,尽管如果您当前的工作树很脏,这很重要,并且会使其变得更加复杂。我是从那个角度来的,并找到了我在下面的答案中分享的过程。 -p 代表什么?【参考方案2】:

要查看最近的存储:

git stash show -p

查看任意存储:

git stash show -p stash@1

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

你可以使用:

git diff stash@0 master

查看与分支 master 相比的所有更改。 或者您可以使用:

git diff --name-only stash@0 master

为了方便查找仅更改的文件名。

【讨论】:

这不回答具体问题。如果您从 master 创建了 stash(为以后保存工作),然后为 master 上的其他工作做一些提交,然后执行 git diff stash@0 master,您将获得与当前 master 的 stash 的差异(包括在 master 上完成的工作在进行存储之后),而不是存储会更改的文件/行,这就是问题所在。 很高兴您回答了这个问题,即使它不是对确切问题的回答。它提供了更多信息,我认为很高兴知道如何在一个分支和你想要比较的任何其他分支之间获得差异。我也喜欢学习 --name-only 标志 :) 这也允许使用自定义差异查看器查看差异,例如git difftool --tool=... stash@0 HEAD @TomDeLeu 很好的观察和重要的一点。要将存储项与其父项进行比较,这似乎可行:git diff stash@0^ stash@0 同样,您可以添加文件名git diff stash@0 master -- filename 以获取对特定文件的更改。【参考方案3】:

如果您的隐藏更改所基于的分支同时发生了更改,则此命令可能有用:

git diff stash@0^!

这会将存储与其基于的提交进行比较。

【讨论】:

太好了,我给~/.gitconfig添加了一个别名:laststash = diff stash@0^! 完美对:git difftool stash^! 用于最后一次存储与它所基于的提交的差异,git difftool stash HEAD 用于最后一次存储与当前提交的差异(stash@n 用于早期存储) 对于那些像我一样从未见过的人^!之前:commit^! is a range specifier which means: this commit, but none of its parents. "git diff stash@0^!"归结为“git diff stash@0 ^stash@0~1 ^stash@0~2 .......”但由于 git diff 只需要 2 次提交,它显示了 stash 之间的差异@0 和 ^stash@0~1 看起来 ^ 在第二次提交的开头没有任何不同,git 忽略它。 你在什么外壳里?我的需要我引用它:git diff 'stash@0^!'【参考方案4】:

如果您的工作树是脏的,您可以通过首先提交脏工作树,然后将其与存储进行比较,将其与存储进行比较。之后,您可以使用脏工作树撤消提交(因为您可能不希望在提交日志中包含该脏提交)。

您还可以使用以下方法将两个存储区相互比较(在这种情况下,您只需首先弹出一个存储区)。

提交你的脏工作树:

git add .
git commit -m "Dirty commit"

用该提交区分存储:

git diff HEAD stash@0

然后,之后,您可以恢复提交,并将其放回工作目录:

git reset --soft HEAD~1
git reset .

现在你已经用你的 stash 区分了肮脏的工作树,并且回到了你最初的位置。

【讨论】:

有没有办法做到这一点,但只能看到将被存储中的内容更改的文件的差异? 2020 这要简单得多;看看我的up-to-date answer。 有趣,我不知道git stash show -l 。它是否将最新的存储与工作(脏)副本区分开来?没有error: switch l requires a value怎么用? 确实如此,它与(可能是脏的)工作副本不同。您只需输入git stash show -l 即可使用它。至于为什么它对你不起作用,我只能猜测你可能使用的是旧版本的 git?我在 git v2.20.1 上,它完美无瑕地工作。【参考方案5】:

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

╔══════════════════════╦═══════════════════════════════╦═══════════════════╗
║ Compare stash with ↓ ║ git diff                      ║ git stash show    ║
╠══════════════════════╬═══════════════════════════════╬═══════════════════╣
║ Local working tree   ║ git diff stash@0            ║ git stash show -l ║
║----------------------║-------------------------------║-------------------║
║ Parent commit        ║ git diff stash@0^ stash@0 ║ git stash show -p ║
║----------------------║-------------------------------║-------------------║
║ HEAD commit          ║ git diff stash@0 HEAD       ║   /               ║
╚══════════════════════╩═══════════════════════════════╩═══════════════════╝

虽然git stash show 第一眼看起来对用户更友好,但git diff 实际上更强大,因为它允许为更集中的差异指定文件名。我个人在zsh git plugin 中为所有这些命令设置了别名。

【讨论】:

这是唯一正确的答案(至少从 git 2.17.1 开始)这是唯一具有“git stash show -l”以及更多信息的答案。非常感谢您发布它 - 我们如何将它推到顶部?给最上面的一个评论?【参考方案6】:

@Magne 的answer 是唯一一个(非常晚)回答问题的最灵活/有用的解释的日期,但它比必要的复杂一点。无需提交和重置,只需存储您的工作副本,比较,然后取消存储。

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

【讨论】:

这种简单的方法(存储然后与另一个存储进行比较)是安全且易于理解的。对于某些用例,您可能还希望使用 git stash save -u 存储未跟踪的文件【参考方案7】:

以防万一,要比较工作树和存储中的文件,请使用以下命令

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

【讨论】:

【参考方案8】:

这适用于 git 版本 1.8.5.2:

git diff stash HEAD

【讨论】:

误导!问题是:我如何才能看到未存储对当前工作树所做的更改?这显示了 stash 和 HEAD 之间的差异,这可能与 git stash apply 应用的差异很大。 请阅读更多关于“我想知道在应用它们之前会做出哪些改变!”的问题。我正在提供一个快速的答案。 您还可以看到所有其他答案都是关于将当前头部(或工作集)与存储区进行比较。为什么只有我的回答具有误导性?这不公平。 @yerlilbilgin 在下面查看我对您的回答的回复。 我们可以省略 HEAD,它是默认的,不是吗?【参考方案9】:

如果你有差异工具(比如无法比较)

git difftool stash HEAD

【讨论】:

误导!问题是:我如何才能看到未存储对当前工作树所做的更改?这显示了 stash 和 HEAD 之间的差异,这可能与 git stash apply 应用的差异很大。 如果您认为这具有误导性,请检查所有其他答案。这不公平! 您会注意到,我将相同的评论复制到了另一个具有误导性的答案(几乎相同的答案)。其他已经有类似评论的答案我独自留下。如果您了解 git stash 的工作原理,那么您将意识到将存储与 HEAD 进行比较并不是应用的内容(这是 OP 所要求的)。实际的“存储”是存储提交与其之前的内容之间的差异。然后将此补丁应用于 HEAD。因此,如果您想知道 OP 的要求,您必须显示 stash 和之前的提交之间的差异,正确答案就是这样做的。 这比任何其他(不必要的)长答案都更直接地回答了这个问题,并且完全按照 OP 的要求执行,除了删除 HEAD。我可以修改@yerlilbilgin 的答案以删除 HEAD,但我认为任何使用 git 的人都可以弄清楚这部分,而我延长答案会降低它的可读性。不怪@yerlibilgin。【参考方案10】:

我相信git diff <current-branchname>..stash@0 是比较本地工作树和最近存储之间变化的最直观的方法。根据需要将stash@0 替换为适用的存储编号。

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

根据git book回答

另外,请注意双点 .. 和三点 ... 指定不同的提交比较,我指的是这个答案的双点。 See the git book for details

【讨论】:

【参考方案11】:

在不移动任何东西的情况下做到这一点的一种方法是利用patch 可以读取 git diff(基本上是统一的 diff)这一事实

git stash show -p | patch -p1 --verbose --dry-run

这将向您展示补丁通常会执行的操作的逐步预览。这样做的额外好处是,补丁也不会阻止自己将补丁写入工作树,如果由于某种原因你真的需要 git 关闭提交前修改,继续并删除 --dry-运行并按照详细说明进行操作。

【讨论】:

【参考方案12】:

结合我在这个帖子和this one 中学到的知识,当我想查看“隐藏的内容”时,我首先运行:

git stash show stash@0

这将显示哪些文件被修改。然后,为了在 difftool 中获得漂亮的视觉差异,我这样做:

git difftool --dir-diff stash@0 stash@0^

这将一次显示给定存储与其父级的所有差异。

您可以在~/.gitconfig 中配置差异工具,例如Meld:

...
[diff]
    tool = meld

【讨论】:

【参考方案13】:

她的藏匿清单

git stash list 
stash@0: WIP on feature/blabla: 830335224fa Name Commit
stash@1: WIP on feature/blabla2: 830335224fa Name Commit 2

所以获取存储号码并执行:

你可以这样做:

 git stash show -p stash@1

但是如果你想要一个差异(这与显示存储的不同,这就是我写这个答案的原因。Diff 考虑你分支中的当前代码,show 只显示你将应用的内容强>)

你可以使用:

git diff stash@0

git diff stash@0 <branch name>

另一件有趣的事情是:

git stash apply
git stash apply stash@10

这会应用隐藏而不将其从列表中删除,您可以git checkout . 删除这些更改,或者如果您很高兴git stash drop stash@10 从列表中删除隐藏。

从这里开始,我从不建议使用git stash pop 并使用git stash applygit stash drop 的组合如果您在错误的分支中应用存储...有时很难恢复您的代码。

【讨论】:

【参考方案14】:

FWIW 这对于所有其他答案可能有点多余,并且与现场接受的答案非常相似;但也许它会帮助别人。

git stash show --help 将为您提供所需的一切;包括藏匿表演信息。

显示 []

将存储中记录的更改显示为存储状态与其原始父级之间的差异。如果没有给出,则显示最新的。默认情况下,该命令显示 diffstat,但它会接受 git diff 已知的任何格式(例如, git stash show -p stash@1 以查看补丁形式的第二个最近的存储)。您可以使用 stash.showStat 和/或 stash.showPatch 配置变量来更改默认行为。

【讨论】:

以上是关于Git diff 与 stash的主要内容,如果未能解决你的问题,请参考以下文章

beyond compare 与git diff整合

git diff 文件对比

Git diff 与 stash

git diff

如何在 2 次提交之间创建一个 git diff/diff-tree/archive 与此时的文件版本(不是头)

Git diff 用法