什么是`git stash show -p @ {0}`的错误语法显示(而不是使用正确的`stash @ {0}`)

时间:2017-10-13 13:31:36

标签: git bash

我正在玩git中的藏匿处并遇到一些看似奇怪的行为。

创造了许多藏匿处后,我想看看它们里面有什么。我跑了git stash show -p,它向我展示了人们所期望的最后一个藏匿的差异。然后我想确认索引0是指最近的存储,所以我(错误地)运行了git stash show -p @{0}。这给了我以下错误:

fatal: ambiguous argument '': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

足够公平。但奇怪的是,它给我带来了一系列变化,我没有认识到这些变化,并且在我的任何一个存储中都不存在。

在这种情况下@{0}指的是什么,差异来自何处?

2 个答案:

答案 0 :(得分:1)

来自gitrevisions(7) manual page (您可以运行git help revisions):

  

@{<n>},例如@{1}

     

您可以使用带有空引用部分的@构造来获取当前分支的reflog条目。例如,如果您在分支blabla上,则@{1}表示与blabla@{1}相同。

答案 1 :(得分:1)

要在kostix's answer上展开一点,git stash代码使用以下原则:

  • “存储(默认存储)由名称refs/stash标识,因此stash@{number}是此引用的reflog条目。
  • 每个存储实际上由两个(或有时三个)提交组成,如Is this a valid visualization of the "git stash" operation?中的图所示stash引用指向工作目录或工作树提交,有两个(如果存在第三个提交,则为三个)父提交。这意味着如果将工作树提交视为由常规Git命令进行的常规提交,则它只是一个合并提交。 (实际上将其视为普通合并可能会产生特殊效果,因此最好使用git stash命令来处理它。)

第二点 - 这是一个实现细节 - 但却非常强烈地影响git stash代码。特别是,当{并且仅当它是合并提交时,git stash将认为任何提交 是有效存储。它实际上并不要求通过refs/stash或其中一个相应的reflog条目命名提交。

如果你写stash@{1}gitrevisions中列出的规则通常会找到refs/stash并提取第1个reflog条目(即第一个,不包括{{ 1}} entry,在技术上根本不是reflog条目:Git只检索引用本身的值,而不是reflog中的条目。)

假设存在stash@{0},这将命名您的一个存储工作树提交,这将是一个合并提交。 stash@{1}代码验证您所提交的提交是“类似存储”,即具有规定的格式。

但这也意味着如果您使用哈希ID或分支名称或任何其他命令运行某些git stash子命令(例如git stashshow)修订解析代码可接受的名称 - 包括类似apply的普通类似于reflog的引用,这意味着“从HEAD中提取的值” - 隐藏代码将尝试使用该代码执行其操作提交。

如果该提交通过了“类似stash”测试,则隐藏代码会将其视为,就好像它是存储一样。由于“stash-like”测试基本上是“是一个合并提交”,@{0}git stash show @{0}会发生的情况是,如果当前提交是合并,git stash show HEAD往往显示它的一部分(从技术上讲,它只是git stash showHEAD^1的区别。如果它合并提交,HEAD应该抱怨并退出:

git stash show

但是旧版本的Git并不总是那么聪明。如果你的Git真的很古老,它可能会尝试显示一些现有的存​​储,将额外的参数传递给'HEAD' is not a stash-like commit 会抱怨它们。