如何在Git-Stash中查看所有目录/文件?

时间:2019-04-30 19:28:55

标签: git

试图弄清楚隐藏的工作方式。我有以下“ git status”

On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   ../../../root/index.tt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    Coupons.pm
    ../../../root/coupons/

no changes added to commit (use "git add" and/or "git commit -a")

当我执行“ git stash save -a”时,发出命令“ git stash show -p”只会显示以下内容,看不到上面的目录或文件“ Coupons.pm”,但是如果我应用了存储,它将返回。

index 629342697e..ecd82eb69f 100644
--- a/View/Web/OmniHUB2/root/index.tt
+++ b/View/Web/SomeSite/root/index.tt
@@ -120,6 +120,9 @@
          <a class="btn btn-primary btn-block" href="/someinterface">SOME Interface</a>
       </div>
       [% END %]
+      <div class="col-xs-12 col-sm-6">
+         <a class="btn btn-primary btn-block" href="/coupons">Coupons</a>
+      </div>
    </div>
 </div>

lines 1-14/14 (END)

2 个答案:

答案 0 :(得分:3)

您可以使用git stash list查看所有现有的存储。你会得到这样的东西:

stash@{0}: WIP on branch-1: 1af3a3456 Add config file
stash@{1}: WIP on branch-1: f8325f42d Update some function
stash@{2}: WIP on branch-2: bae22df24 Merge branch 'branch-3' of

您可以使用git stash show -p stash@{2}查看特定存储的差异。

您绝对应该阅读https://git-scm.com/docs/git-stash

上的git-stash文档

答案 1 :(得分:2)

TL; DR

git stash的工作原理非常简单。是后果变得很复杂。在这种情况下,您的未跟踪文件处于额外提交状态,git stash show不会显示出来。

要显示此额外提交中的内容,可以使用:

git show stash^3

将显示添加的每个此类文件。

git stash的作用是进行两次提交(有时是三次提交,而您正在使用第三种提交模式),这两个提交都不在任何分支上。所需的两次提交将保存 index 的内容和 work-tree 的内容。第三次提交(如果存在)保存未跟踪的文件(忽略的文件除外)或未跟踪的文件(不包含其他文件)。

因此, 中的提交是两个(或三个)快照,以及每个提交随附的其余元数据,即两个(或三个)元数据块。除了一个例外,这些块中的元数据并不是特别有用,并且可以被忽略。

这里也值得一提git status的工作原理,因为它们是相关的。您需要了解以下事实:Git提供了称为 index staging area 或(通常是现在) cache < / em>,具体取决于Git的哪个部分正在执行调用。由于这主要是关于git stash的,因此我在这里只说git status进行两次比较:将HEAD与索引进行比较以查找其调用的内容准备提交的文件,然后分别对索引和工作树进行比较,以查找其所谓的未准备提交的文件

背景

您可能已经知道,每个Git提交都保存着所有源文件的完整快照(嗯,提交时跟踪的所有文件)。您可能还知道提交包含元数据:(用户名和电子邮件地址),创建时间(日期和时间戳),原因(日志消息)以及提交的哈希ID的原因。提交的 parent:在此提交之前的提交。每个提交都具有自己的唯一哈希ID,该ID与其他提交的ID不同,但是计算方式使宇宙中的每个Git都同意那个提交得到那个哈希ID。

因为每个提交都记住其前身的哈希ID,所以我们只需要知道任何提交链中 last 提交的哈希ID:

A <-B <-C   (need C's hash ID)

我们让Git读取提交C来找到B的哈希ID,然后读取B来找到A的哈希ID。像master这样的分支名称仅保存该系列中 last 提交的哈希ID。

要进行 new 提交,Git只需立即保存索引 中的内容,添加您的姓名和电子邮件,依此类推,设置 parent < / em>到 current 提交,并将所有内容写为新提交,这将生成新提交的新的唯一哈希ID。我们将新提交称为D,并且D指向C,因此我们将其绘制为:

A--B--C   <-- branch
       \
        D

要记住D已添加到分支branch中,Git现在将D的新哈希ID填充到 name branch中,给我们:

A--B--C--D   <-- branch

由于各种原因,包括节省大量空间,提交中的文件采用特殊的只读,仅Git,冻结,压缩形式。只有Git可以使用它,没有人甚至Git都不能 change 其中的任何一个。尽管这不是Git的正式术语,但我还是称这些文件为“冻干”。

您当然需要将文件解冻并重新水化。这些文件进入您的工作树,您可以在其中看到它们并对其进行处理。因此,每个文件肯定有两个副本:在当前提交中冻干的一个副本,以及工作树中的可用版本。

Git将索引/暂存区域添加为着陆点或启动点之间的部分:索引中也有文件的冻干副本。不过,与提交的版本不同,您可以随时替换一个。这就是git add的作用:它将工作树副本冻干,并将其写入索引,以替换先前的索引副本,或者在索引中创建文件以前没有。

Git保存 index 中的内容而不是 work-tree 中的内容的事实是为什么我们必须如此频繁地运行git add的原因。它也使git commit变得非常快:无需扫描整个工作树,无需重新压缩每个文件以查看其是否已更改。 git add删除重要文件时,您已经对其进行了重新压缩。冻干的索引副本已采用正确的格式以进行新的提交。 Git可以将它们打包并完成。

已跟踪文件与未跟踪文件

跟踪文件的定义非常简单:它是现在索引为 的任何文件名。由于git commit保存了索引中的内容,因此文件的跟踪版本就是新提交中的内容。现在工作树中的内容无关紧要:文件只必须在索引中即可。不管它有什么形式, 就是要提交的内容。

因此,未跟踪文件的定义也非常简单:它是名称在工作树中但不在索引中的任何文件。 (如果它既不在工作树的索引 nor 中,则根本不存在。有多少个不存在的文件不在索引或工作树中?现在?:-)实际上在大多数系统上都有一个可数的答案,但是数量如此之多,不值得过多考虑:例如,在Linux上约为254 255 。)未被跟踪的文件可以被简单地取消跟踪,在这种情况下,Git有时会抱怨该文件,也可以被取消跟踪并且被忽略来关闭投诉。

(没有被跟踪但被忽略的文件:如果文件被跟踪,它就不会被定义忽略。可以在文件中的 中设置一些特殊状态位索引,但我们不要在这里讨论。)

git stash的提交

the git stash documentation中间,他们提到IW提交,我通常将其称为iw提交。 stash命令的工作是在不更改当前分支的情况下进行这些提交,然后更新refs/stash(而不是分支名称)以保存其哈希ID之一。这足以找到两个提交。

隐藏代码几乎以通常的方式提交i。正如我们在上面看到的,git commit通过包裹冻干的文件,设置元数据(以父级为当前提交),写出提交并将新提交的哈希ID写入当前分支来进行提交。名称。如果我们只是停止git commit进行 last 步骤,然后将哈希ID保存在其他位置,那么我们将得到所需的信息:

A--B--C--D   <-- branch
          \
           i   (git-stash will save i's hash ID somewhere)

现在git stash需要以某种方式保存当前的工作树,如果您要保存它,还需要保存第三次提交。现在让我们假设我们不需要第三次提交,只需将w提交一次即可。我们想要进行设置,以便w保留所有被跟踪的工作树文件的副本。为此,存储代码将创建第二个临时索引,并将所有文件的所有工作树版本复制到其中。它使用一些棘手的代码来避免不必要的重新冷冻干燥,但是原则上它只是:

for (every file $f in the real index): copy $f into temporary index

然后,隐藏代码使用w 作为其(两个)父级,通过此临时索引进行i提交:

A--B--C--D   <-- branch
         |\
         i-w   (git-stash now has w's commit hash too)

然后,git stash仅将w添加到refs/stash,如果已经存在refs/stash,则使用推式操作;如果不存在,则创建refs/stash:< / p>

A--B--C--D   <-- branch
         |\
         i-w   <-- refs/stash

稍后,我们将介绍git stash的最后几位。

三提交隐藏中的第三次提交

如果您选择进行第三次提交(我将u称为“未跟踪”文件),则隐藏代码会在写入之前在 中写出第三次提交退出w提交。为了进行提交,git stash列出了所有未跟踪的文件,包括(-a / --all)或排除(-u / --include-untracked)被忽略的子集未跟踪的文件。然后,它会执行类似于w提交的技巧:它会创建一个临时索引,然后将列出的每个文件复制到该临时索引中,并从中进行u提交。

stash代码为u提交 no 父级。这个u提交只是悬挂在那里,没有附加任何东西:

A--B--C--D   <-- branch
         |
         i

         u

然后,在同时完成iu提交的情况下,git stash返回到w提交的状态,使用以前的临时索引并复制工作-根据它们在实/常规索引中的存在将树文件放入其中。然后,当它进行w提交时,它给w一个第三父级,即刚刚进行的u提交:

A--B--C--D   <-- branch
         |\
         i-w   <-- refs/stash
          /
         u

,然后像以前一样将w提交的哈希ID写入refs/stash

创建存储的最后一步是清理索引和工作树

git stash已经进行了这两次或三次提交,现在必须清理索引和工作树。此处的默认设置只是运行git reset --hard,它将所有冻结的文件从当前提交复制到索引,然后再复制到工作树。使用-u-a进行第三次提交时,git stash也使用git clean或等效的命令来删除它在该第三次提交中放置的任何文件。

(使用--keep-index选项,git stash重置工作树以匹配索引,索引不保留它,以便索引匹配i提交。{{ 1}}或-a保持不变。)

三提交隐藏的后果

为了正确地还原(-upop)存储,Git需要索引和/或工作树中的文件是“干净的”。对于两次提交的存储,Git并没有提出严格的要求:它只是尝试将存储合并到当前工作树中。后果可能是一团糟,在某些情况下很难或不可能扭转它。这意味着apply如果git stash apply说除了什么都不做,可以清除树的消息,git stash popgit status通常是不明智的;但这是您的选择。 >

但是,对于三个提交的存储,Git更加小心。奇怪的是,这可能会令人沮丧。特别是,Git尝试不破坏存在的,未跟踪的任何工作树文件,并通过从u提交中检出文件来覆盖它们。本质上,这意味着您通常必须运行git clean只是为了检查由-a-u制成的存储。

当您成功提取这样的存储时,Git将具有:

  • u个提交文件提取到工作树中(这些文件现在应该都是新的,并且已被取消跟踪,并且根据与那时相比.gitignore文件的状态,可能类似地被忽略了) /不像以前一样被忽略)。
  • w提交文件与您现有的工作树合并。
  • 如果您使用的是--index,请使用i将与父级进行比较的git apply --cached应用于您现有的索引。

其中两个步骤与所有隐藏相同。

如果存储附加到提交D,并且索引和工作树是原始的且匹配D,则git stash apply --index将始终成功(除非存在任何git stash错误那是)。因此:

git checkout $(git rev-parse refs/stash^1)
git reset --hard
git stash apply --index

将完全应用两次提交的存储并完全从git stash恢复状态,但是对于三个提交的存储,必须使用git clean或{添加一个-df命令{1}}删除-dfx文件。请注意,ugit reset --hard都可能破坏未保存在Git中任何地方的工作,因此,最好确保将这些工作保存在某个地方(也许很奇怪,使用{{1} } :-))。