git rebase:以下未跟踪的工作树文件将被签出覆盖(尽管已跟踪文件)

问题描述 投票:1回答:2

[尝试进行交互式变基时,git说:

error: The following untracked working tree files would be overwritten by checkout:
        # some files here
Please move or remove them before you switch branches.
Aborting
error: could not detach HEAD

有问题的文件集似乎会有所不同,具体取决于我为(e)dit标记的提交。它们都是被跟踪的文件,它们已经沿着分支中的提交进行了修改,然后最终在后续提交中被删除。

为什么git这样做?我该如何解决?

谢谢!

git rebase
2个回答
1
投票

Git抱怨,因为文件未跟踪。

我知道你说过:

[[the]文件被跟踪

但不是:您还说过:

它们在以后的提交中最终被删除。

在发生故障时,文件已从索引中删除,但未从工作树中删除。这就是untracked file:的定义,它是工作树中的文件,但不在索引中。

特别是这个:

error: could not detach HEAD

告诉您(或者,无论如何,告诉我)在您现在签出的提示提交中,当您输入命令时,文件当前未被跟踪:

git rebase -i <start-point>

但是这里由标识的提交中有它们。 Git将需要git checkout该提交,但是在签出该提交时,它将用跟踪的文件覆盖未跟踪的文件。

如果最后一点给您带来record-scratch / WTF噪音😀,请放心:这确实令人困惑。Git中的索引是至关重要的小野兽,通常无法正确解释。要理解它,您必须意识到Git始终具有您正在使用/正在使用的每个文件的

three

-<< upup >> 3个副本。一次提交一直冻结一次副本:您现在已签出的提交。第二个副本1位于index中。这就是使文件tracked的原因。第三份副本是您唯一可以参见 ...的副本,但是Git甚至不使用它,因为它是工作树中的您的副本。索引,Git也称为staging area,它保存每个文件的副本(再次参见脚注1),该副本将进入

您下一次提交的文件

。这样,当您选择要进行的提交时,它最初是复制您git checkout中的提交的out。然后,Git将索引副本以特殊的Git格式复制到您的work-tree中,这是Git放置所有快照文件供您查看和使用的地方。
一旦Git复制了这些内容,大部分就完成了。您对工作树副本进行了更改,然后运行git add告诉Git:将工作树副本复制回索引副本中/上方的索引副本中。 (再次,请参见脚注1。)这样做的原因有些复杂,但是如果您愿意,可以这样考虑:

提交中的副本是只读的,一直冻结。为了节省大量空间,Git将它们保留为仅Git可以使用的特殊的仅Git压缩格式。

    这对于存档很有意义,但是对于完成[[work
则毫无用处,因此Git必须将文件扩展为正常格式。那是

  • work-tree副本。
  • [为了使事情变得更快,并使事情对Git方便,Git将冻结的副本(但不再冻结)保留在索引中。您可以通过从工作树中单击git add来替换批发的索引副本:Git将其放入索引中已准备好提交的冻干format中(但仍可以在其中替换) 。
  • 您可以使用工作树副本执行任何所需的操作,因为它是常规文件。只要工作树文件存在,它就作为文件存在。
  • 您可以随时删除或替换
  • 索引副本。要替换它,请使用git add将工作树文件复制到该名称下的索引中。要完全删除它,请使用git rm file

    运行git commit时,Git打包

    索引中的所有文件

    以创建新提交的快照。索引中的任何内容(无论索引中具有什么形式)都将进入新提交。 Git根本不使用您的工作树。这就是为什么您必须一直重新git-add文件的原因:Git不在查看工作树副本。2

    如果工作树文件存在并且索引副本为gone,则该文件为untracked。但是,如果文件位于某个更早的

    commit

    中,并且您签出了该提交,则来自较早提交的副本将被back into索引,然后再次跟踪该文件。而且,当来自较早提交的副本进入索引时,Git也会覆盖工作树中的副本-除非这样做会浪费它,因为它没有保存在任何地方,在这种情况下,Git表示这样做。 >((如果被跟踪,Git会知道它是否安全地保存在提交中。如果是,则Git可以覆盖它。)因此,现在该怎么办了:如果数据很重要,请将文件移到其他位置。做你的基础。完成后,文件将为[[gone,因为最后一次提交将其删除。现在,您可以将文件移回,并且不会再次跟踪它们。先前具有文件的提交现在仍具有文件;如果您的基准将这些提交复制到新的和改进的提交中,则这些新的和改进的提交仍然具有文件。

    关键概念:

    文件是

    tracked

    还是untracked取决于索引中是否有副本。索引副本大部分是不可见的,

    3

    却非常重要! 索引是一个临时区域。它主要包含您要进行的next提交;当您git checkout提交时,Git必须从提交中填写因此,某些文件的跟踪/未跟踪状态可能会突然改变。当Git填充索引from提交时,它将在索引中创建一个文件(如果需要)[删除
    文件(如果不在您要移动的提交中),并且在那时,它将删除文件

    工作树也是如此。1从技术上讲,索引包含要提交的每个文件的blob对象的reference。就像索引一样,blob对象始终被冻结,并且提交引用了该对象。当您git add一个文件时,Git会压缩和散列内容,如果已经有一个包含该数据的Blob,则Git可以重新使用现有的Blob。否则,Git会创建一个新的,并且该blob的哈希将进入索引。有时,这会创建一个永远不会使用的blob,因为您在其中写入了一个版本,然后意识到其中存在错误,然后在其中写入了另一个版本。那没关系:Git一直在自行创建垃圾对象。 Git有一个
    garbage collector
    ,只要看起来合理,它就会运行以清除未使用的对象。

    2如果使用git commit -a,则会创建一个second但临时索引,git add -s将所有文件都移到该临时索引,并从该临时索引提交。如果一切正常,则临时索引将成为新索引;如果失败,Git只会删除临时索引,然后一切都会恢复到运行git commit -a之前的状态。 TL; DR是Git仍从索引提交。只是第二个额外索引而已。

    3 git status命令

    compares

    索引与HEAD提交的比较,并告诉您什么是[[different。因此,如果文件“丢失”,您会看到一个删除内容,为stage for commit
    。然后,它分别将索引与工作树进行比较,并告诉您什么是[[different。因此,如果文件在索引中但在工作树中丢失,您将看到一个删除,其删除内容为未暂存以提交。

    如果文件存在于HEAD中,但在索引中gone,然后在工作树中为back,您会看到分阶段删除and未跟踪的文件,两者名称相同。

    假设您有:

    提交历史,其中修改了文件foo.txt,然后将其删除;此刻,在您跟踪的文件旁边,您的磁盘上还有一个未跟踪的foo.txt版本。

    © www.soinside.com 2019 - 2024. All rights reserved.