我认为它们应该基本相同,但是当我尝试
$ git stash show -p stash@{N}
和
$ git show stash@{N}
后者显示了一些额外的提交信息,但实际差异要短得多。 (前者显示大约十几个文件,但后者只显示一个。)
那么,这两者究竟有什么区别,为什么会不同呢?
我还可以依靠诸如
git diff stash@{M} stash@{N}
之类的东西吗?正确吗?
最佳答案
收纳袋
保存的东西 git stash
是我调用 "stash bag" 的原因.它由两个单独的提交组成:“索引”提交(暂存区)和“工作树”提交。工作树提交是一种有趣的 merge 提交。
让我在这里再次绘制(请参阅更长版本的引用答案),只是为了正确说明它。为简单起见,让我们假设您有一个只有一个分支和三个提交的小型存储库,A
通过 C
.您在一个分支上并进行一些更改,然后运行 git stash save
(或只是简单的 git stash
)。这是你得到的:
A - B - C <-- HEAD=master
|\
i-w <-- the "stash"
现在你可以创建(或切换到)另一个分支,但为了说明,假设你把那个存储留在那里,并在
master
上进行更多的“常规”提交。 :A - B - C - D - E <-- HEAD=master
|\
i-w <-- stash
这里的重点是“stash 袋”,一对
i
索引和 w
ork-tree 提交,仍然像以前一样挂起相同的提交。提交无法更改,对于 stash-bag 提交也是如此。但是现在您通过进行一些更改(仍然在
master
上)并运行 git stash save
来创建一个新的存储库。再次。旧的储物袋怎么办? “引用名称”2
stash
,现在指向新的储物袋。但是旧的 stash-bag 提交仍然在那里。他们现在需要一个“reflog”样式名称,stash@{1}
.3无论如何,你现在拥有的是:
A - B - C - D - E <-- HEAD=master
|\ |\
i-w i-w <-- stash
.
-------------- stash@{1}
(当您使用
git stash drop
时,stash 脚本简单地操作 stash
ref 的引用日志以删除丢弃的 stash-bag 的 ID。这就是为什么所有“更高”的都被重新编号。实际的 stash-bag 本身是在下一个 git gc
上收集垃圾。)下一点是了解正在发生的事情的关键。
任何时候 git 需要你命名一个特定的提交,你都可以用许多不同的方式来完成。
每个提交都有一个“真名”,即你看到的丑陋的 SHA-1 哈希值,例如
676699a0e0cdfd97521f3524c763222f1c30a094
.你可以这样写。它总是意味着相同的提交。提交永远无法更改,这是提交全部内容的加密散列,因此如果该特定提交存在,则该值始终是其名称。不过,这对人们来说并不是一个好名字。所以我们有别名:像分支和标签名称这样的东西,以及像
HEAD
这样的相对名称。和 HEAD~2
, 以及类似 HEAD@{yesterday}
的 reflog 样式的名称或 master@{1}
. (有一个命令, git rev-parse
,可以将这样的名称字符串转换为哈希值。试试看:运行 git rev-parse HEAD
, git rev-parse stash
等等。git 中的大多数东西使用 git rev-parse
或它的大哥更多, git rev-list
,将名称转换为 SHA-1 值。)(有关如何命名修订的完整描述,请参阅 gitrevisions 。Git 使用 SHA-1 不仅仅是提交,但在这里让我们只考虑提交。)
Git stash show、git show 和 git diff
好的,终于可以联系到您的
git show
对比 git stash show
, 和 git diff
等等。让我们解决 git stash show
首先,因为那是您应该与 stash 一起使用的那个。此外,git stash
子命令将验证您命名的提交——或者,如果您未命名提交,则验证通过 stash
找到的提交。引用——“看起来像”一个 stash,即是这些有趣的 merge 提交之一。如果您运行
git stash show -p
, git 向您显示一个差异 ( -p
atch)。但它究竟显示了什么?回到带有储物袋的图表。每个 stash-bag 都卡在一个特定的提交上。上面,“主要”存储现在卡在提交
E
上。 ,以及 stash@{1}
较早的藏品卡在 C
.什么
git stash show -p
确实是比较存储的工作树提交,w
, 针对存储挂起的提交。 4你当然可以自己做。假设您要比较
w
在 stash
, 挂起提交 E
, 反对提交 E
,可以通过分支名称master
来命名.所以你可以运行:git diff master stash
.这里的名字stash
指的是(当前)存储提交 w
, 和 master
指的是提交 E
,所以这会产生与 git stash show -p stash
完全相同的补丁. (而且,如果您想将 w
中的 stash@{1}
与提交 C
进行比较,您只需要运行 git diff
这样您就可以命名这两个提交。当然,仅使用 git stash show -p stash@{1}
会更容易。)5普通的怎么样
git show
?这有点复杂。 git show
很高兴展示一个提交,你给了它一个 stash
引用(stash
本身,或 reflog 变体之一)。这是一个有效的提交标识符,它解析为 w
之一。工作树在其中一个存储袋中提交。但是git show
当它看到 merge 提交时,行为会有所不同。正如文档所说:It also presents the merge commit in a special format as produced by
git diff-tree --cc
.
所以
git show stash@{1}
向您显示“组合差异”,假设提交 w
是提交的正常 merge C
和 i
, 生产 w
.这毕竟不是正常的 merge ,尽管 merge 的差异实际上可能很有用,前提是您知道自己在看什么。阅读 --cc
git diff-tree
下的文档详细了解它是如何工作的,但我会注意到 --cc
暗示 -c
其中包括这一点:... lists only files which were modified from all parents.
在
stash
的情况下, 如果您有 git add
-ed 运行前的文件 git stash
,使 i
-vs- w
diff 为空,您不会在此处的输出中看到这些文件。最后,如果您
git diff stash@{M} stash@{N}
: 这只是问git diff
比较不同的w
ork-tree 提交。这有多少意义,取决于你在比较什么,这通常取决于 stash 袋的连接位置。1两个或三个,真的,但我要把它画成两个。你得到了两次提交
git stash save
(或普通 git stash
,这意味着 git stash save
)。如果添加 -u
,您将获得三个提交或 -a
保存未跟踪或所有文件的选项。这会影响存储恢复,但不会影响 git stash show
的输出命令。2“引用名称”只是一个名称,而类似于分支或标签名称。引用名称有多种可能的形式。分支和标签只是具有特殊用途的名称。 “远程分支”是这些引用的另一种形式,“stash”也是一种引用。
事实上,
HEAD
只是另一个引用,虽然它是一个非常特殊的引用。我很重要,如果你删除 HEAD
文件,git 将决定您的存储库毕竟不再是存储库。除了一些特殊情况—
HEAD
, ORIG_HEAD
, MERGE_HEAD
,等等——所有引用都以字符串 refs/
开头.分支以 refs/heads/
开头, 标签以 refs/tags/
开头,“远程分支”以 refs/remotes/
开头.换句话说,引用有一个“命名空间”,通常以 refs/
开头。然后在下面加上另一个词来确定他们住在哪里。存储引用拼写为
refs/stash
(并停在那里,没有 refs/stash/jimmy_kimmel
或类似的东西)。3事实上,这确实使用了reflog。这意味着,除其他事项外,除了“主要”存储之外,
refs/stash
,遗嘱可以过期。 (幸运的是,作为 musiphil notes ,自 git 1.6.0 以来的默认设置是这些不会过期;您必须为它们配置过期时间才能实现这一点——无论如何,这可能不是您想要的。)4它使用后缀
^
的巧妙方法符号,在我的 other answer 中有详细说明.5如果你想看
i
怎么办?这些 stash 袋中的 ndex 提交?啊,好问题! :-) stash 脚本没有很好的答案。查看这些的简单方法是使用 ^2
后缀来命名每个存储的第二个父级,即 i
提交。而且,如果您有一个包含未跟踪文件或所有文件的第三次提交的存储,那就是第三个父项:commit w
看起来像一个三父 merge 和 stash^3
到达第三个。但是,w
不是正常的 merge ,所以很棘手。查看 stash 的所有部分的最好的简单方法可能是使用 git stash branch
将它变成自己独立的分支。 .
关于git - `git stash show -p stash@{N}` 和 `git show stash@{N}` 之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21738579/