何时进行跟踪但不进行暂存或取消暂停,但不进行无人跟踪

时间:2016-11-09 22:12:42

标签: git

我在SO上看过following问题,它询问如何跟踪但不能分阶段以及如何取消暂停但不在git中取消攻击文件。作为一个git初学者,我很好奇这两个案例在哪些特定场景中有用?

1 个答案:

答案 0 :(得分:0)

从技术上讲,你不能"跟踪而不是阶段"一个文件,也不是某种意义上的#34;没有未跟踪",除了Git和人都使用" unstage"引用别的东西。 (我将描述"非舞台"稍微结束意义。)

跟踪文件""在Git中,如果它有一个Git称之为" index",又名" staging area"的条目。 git addgit rm都会在索引中创建或替换一个条目 - git rm放入一个" whiteout"输入,意思"它刚才在这里,但在我提交后,让它不在这里,以便它不再被跟踪。" (事实上​​,git add可以像git rm --cached那样行事,如果文件在索引中但在工作树中丢失,则会这样做。)

您可以使用git ls-files --stage查看(大部分)索引中的内容;见下面的例子。最多有四个索引"插槽"每个文件路径名称。其中三个仅在合并期间使用。因此,除了合并之外,索引中的所有内容始终处于"阶段零"。

暂存文件,我们只需运行git add path(或git add -- path,如果路径部分类似于{{{ 1}},虽然您也可以将文件-p命名为-p,以防止它看起来像补丁标记)。如果文件已经在索引中,则更新(通过替换现有索引条目)。

To" unstage"一个文件,我们通常运行./-p(必要时添加git reset path,如前所述)。但是,除了一个案例,此不会删除路径的索引条目!相反,它重置(因此名称)索引条目以匹配--提交。完全删除条目的一种情况是HEAD提交在该路径名下没有文件。

因此," unstaging"一个文件实际上不是 un -stage文件:相反,它重新 - 阶段(或更好,重置)它回到当前(HEAD)提交,但不触及工作树中的副本。但是,每个人都使用" unstage"对于这个动作,所以我们不妨习惯它。 : - )

进入杂草(回答你的其他问题)

您与使用HEAD的谈话相关联的问题。这在Git版本2.5中已经完全被破解了一段时间,并且在Git 2.10.1中仍然部分被破坏了(我只是在我的测试中)。它有效地将占位符放入索引中,以便 跟踪文件(当然,因为它在索引中),但同时在那里没有实际的文件。此索引条目标记为" special",非常类似于whiteout条目。该行为实际上与whiteout条目非常相似 - 即,git add -N 将文件写入结果树 - 除了在提交后保留意图添加特殊条目,而提交后将删除whiteout条目。

至于使用这有什么:在我看来,它没有。 :-)显然,解决错误(2.5以下的Git版本git write-tree完全失败,2.5到2.10中的小问题)并不是非常重要,因此可能很少有人(如果有的话)实际使用它。

它确实完成的一件事是让-N将文件视为已跟踪,以便将当前索引与工作树进行比较的git diff将文件的内容显示为加入:

git diff

(这表示"第三个文件"未跟踪)

$ git status --short
?? thirdfile

(无输出:$ git diff 不查看未跟踪的文件)

git diff

(这表明该文件现在在索引中被跟踪,而不是在$ git add -N thirdfile $ git status --short AM thirdfile 提交中,因此状态HEAD作为第一个字母 - 并且也被修改,因为索引条目是假的但该文件存在真实内容)

A

(这里我们看到真实的内容)。如果我们使用$ git diff diff --git a/thirdfile b/thirdfile index e69de29..1ecbedd 100644 --- a/thirdfile +++ b/thirdfile @@ -0,0 +1 @@ +data for file 3 来查看索引,我们会看到 1 一个阶段为零的条目 - 一个普通文件 - 其哈希是空文件的哈希:

git ls-index --stage

如果我们清空文件,工作树中的真实文件现在与存储在索引中的哈希相匹配。奇怪的是,虽然$ git ls-files --stage 100644 e5c143f6fec374d115ef674fc036649d78c625d2 0 README 100644 6b8bd59d197cba9032b59ee3aa3f4e71cfbdc2df 0 dummyfile 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 thirdfile $ git hash-object -t blob --stdin < /dev/null e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 现在没有显示任何内容,git diff仍然表示文件被修改,与索引版本相比:

git status

(最后一个命令不产生输出)。这是一个文件,其缓存条目被标记为&#34;意图添加&#34;始终被视为&#34;修改&#34;当与工作树相比时,是Git 2.10.1&#34;中部分断开的来源。 case,因为即使新提交的内容与$ : > thirdfile $ git status --short AM thirdfile $ git diff 提交内容相匹配,这也会使git commit愚弄允许提交。

一旦你HEAD(没有git add)文件,假冒&#34;意图在索引中添加&#34; -flagged stage-0条目就成了真实blob的真实条目(即文件),其中实际哈希指向存储库中的真实对象。也就是说,真正的条目会覆盖假的条目。如果您首先从工作树中删除该文件,然后在该路径上运行-N,Git将完全删除特殊标记的索引条目,就像Git在其上运行git add一样。这与在真实(非特殊标记)文件上使用git rm --cached不同,Git在索引中写入了一个white-out条目。 2

1 目前尚不清楚为什么 git rm --cached会显示这些意图添加标记的条目。相同的命令跳过白名单。

2 我们可以使用git ls-files --staged查看whiteout条目。我们只需在工作树中创建文件,或使用git status --short,以便在将white-out条目写入索引时文件保留在工作树中。此时git rm --cached 显示文件,git ls-files --stage将文件显示为已删除,git diff将文件显示为已删除以及未跟踪,git status为文件生成两个条目:

git status --short

要拥有$ git rm --cached secondfile $ git status --short D secondfile ?? secondfile ?? thirdfile 条目,索引中必须包含某些内容;但要获得D条目,Git必须假装索引中没有任何内容。因此,此处有一个??的whiteout条目,在索引的某些扫描中可见,但secondfile没有,这只是我刚才在索引中作为其中一个意图添加虚假条目。